summaryrefslogtreecommitdiffstats
path: root/toolkit/content/widgets/datetimebox.xml
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/widgets/datetimebox.xml')
-rw-r--r--toolkit/content/widgets/datetimebox.xml156
1 files changed, 132 insertions, 24 deletions
diff --git a/toolkit/content/widgets/datetimebox.xml b/toolkit/content/widgets/datetimebox.xml
index 5859f80dd..c276265a3 100644
--- a/toolkit/content/widgets/datetimebox.xml
+++ b/toolkit/content/widgets/datetimebox.xml
@@ -4,6 +4,11 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<!DOCTYPE bindings [
+<!ENTITY % datetimeboxDTD SYSTEM "chrome://global/locale/datetimebox.dtd">
+%datetimeboxDTD;
+]>
+
<bindings id="datetimeboxBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
@@ -21,12 +26,13 @@
<implementation>
<constructor>
<![CDATA[
- // TODO: Bug 1320227 - [DateTimeInput] localization for
- // <input type=date> input box
- this.mMonthPlaceHolder = "mm";
- this.mDayPlaceHolder = "dd";
- this.mYearPlaceHolder = "yyyy";
+ /* eslint-disable no-multi-spaces */
+ this.mYearPlaceHolder = ]]>"&date.year.placeholder;"<![CDATA[;
+ this.mMonthPlaceHolder = ]]>"&date.month.placeholder;"<![CDATA[;
+ this.mDayPlaceHolder = ]]>"&date.day.placeholder;"<![CDATA[;
this.mSeparatorText = "/";
+ /* eslint-enable no-multi-spaces */
+
this.mMinMonth = 1;
this.mMaxMonth = 12;
this.mMinDay = 1;
@@ -76,6 +82,7 @@
if (this.mInputElement.value) {
this.setFieldsFromInputValue();
}
+ this.updateResetButtonVisibility();
]]>
</constructor>
@@ -107,9 +114,11 @@
this.mYearField.setAttribute("typeBuffer", "");
}
- if (!aFromInputElement) {
+ if (!aFromInputElement && this.mInputElement.value) {
this.mInputElement.setUserInput("");
}
+
+ this.updateResetButtonVisibility();
]]>
</body>
</method>
@@ -170,6 +179,13 @@
<method name="setInputValueFromFields">
<body>
<![CDATA[
+ if (!this.isAnyValueAvailable(false) && this.mInputElement.value) {
+ // Values in the input box was cleared, clear the input element's
+ // value if not empty.
+ this.mInputElement.setUserInput("");
+ return;
+ }
+
if (this.isFieldInvalid(this.mYearField) ||
this.isFieldInvalid(this.mMonthField) ||
this.isFieldInvalid(this.mDayField)) {
@@ -192,6 +208,10 @@
let date = [year, month, day].join("-");
+ if (date == this.mInputElement.value) {
+ return;
+ }
+
this.log("setInputValueFromFields: " + date);
this.mInputElement.setUserInput(date);
]]>
@@ -217,6 +237,9 @@
if (!this.isEmpty(day)) {
this.setFieldValue(this.mDayField, day);
}
+
+ // Update input element's .value if needed.
+ this.setInputValueFromFields();
]]>
</body>
</method>
@@ -302,6 +325,12 @@
let targetField = aEvent.originalTarget;
let key = aEvent.key;
+ // Home/End key does nothing on year field.
+ if (targetField == this.mYearField && (key == "Home" ||
+ key == "End")) {
+ return;
+ }
+
switch (key) {
case "ArrowUp":
this.incrementFieldValue(targetField, 1);
@@ -406,11 +435,13 @@
}
aField.value = value;
+ this.updateResetButtonVisibility();
]]>
</body>
</method>
- <method name="isValueAvailable">
+ <method name="isAnyValueAvailable">
+ <parameter name="aForPicker"/>
<body>
<![CDATA[
return !this.isEmpty(this.mMonthField.value) ||
@@ -492,6 +523,7 @@
if (this.mInputElement.value) {
this.setFieldsFromInputValue();
}
+ this.updateResetButtonVisibility();
]]>
</constructor>
@@ -551,7 +583,7 @@
}
this.log("setFieldsFromInputValue: " + value);
- let [hour, minute, second] = value.split(':');
+ let [hour, minute, second] = value.split(":");
this.setFieldValue(this.mHourField, hour);
this.setFieldValue(this.mMinuteField, minute);
@@ -617,6 +649,13 @@
<method name="setInputValueFromFields">
<body>
<![CDATA[
+ if (!this.isAnyValueAvailable(false) && this.mInputElement.value) {
+ // Values in the input box was cleared, clear the input element's
+ // value if not empty.
+ this.mInputElement.setUserInput("");
+ return;
+ }
+
if (this.isEmpty(this.mHourField.value) ||
this.isEmpty(this.mMinuteField.value) ||
(this.mDayPeriodField && this.isEmpty(this.mDayPeriodField.value)) ||
@@ -652,6 +691,10 @@
time += "." + this.mMillisecField.value;
}
+ if (time == this.mInputElement.value) {
+ return;
+ }
+
this.log("setInputValueFromFields: " + time);
this.mInputElement.setUserInput(time);
]]>
@@ -678,6 +721,9 @@
if (!this.isEmpty(minute)) {
this.setFieldValue(this.mMinuteField, minute);
}
+
+ // Update input element's .value if needed.
+ this.setInputValueFromFields();
]]>
</body>
</method>
@@ -721,9 +767,11 @@
this.mDayPeriodField.value = "";
}
- if (!aFromInputElement) {
+ if (!aFromInputElement && this.mInputElement.value) {
this.mInputElement.setUserInput("");
}
+
+ this.updateResetButtonVisibility();
]]>
</body>
</method>
@@ -793,6 +841,7 @@
this.mDayPeriodField.value == this.mAMIndicator ?
this.mPMIndicator : this.mAMIndicator;
this.mDayPeriodField.select();
+ this.updateResetButtonVisibility();
this.setInputValueFromFields();
return;
}
@@ -850,6 +899,7 @@
this.mDayPeriodField.value = this.mPMIndicator;
this.mDayPeriodField.select();
}
+ this.updateResetButtonVisibility();
return;
}
@@ -905,16 +955,30 @@
}
aField.value = value;
+ this.updateResetButtonVisibility();
]]>
</body>
</method>
- <method name="isValueAvailable">
+ <method name="isAnyValueAvailable">
+ <parameter name="aForPicker"/>
<body>
<![CDATA[
+ let available = !this.isEmpty(this.mHourField.value) ||
+ !this.isEmpty(this.mMinuteField.value);
+
+ if (available) {
+ return true;
+ }
+
// Picker only cares about hour:minute.
- return !this.isEmpty(this.mHourField.value) ||
- !this.isEmpty(this.mMinuteField.value);
+ if (aForPicker) {
+ return false;
+ }
+
+ return (this.mDayPeriodField && !this.isEmpty(this.mDayPeriodField.value)) ||
+ (this.mSecondField && !this.isEmpty(this.mSecondField.value)) ||
+ (this.mMillisecField && !this.isEmpty(this.mMillisecField.value));
]]>
</body>
</method>
@@ -963,7 +1027,8 @@
<content>
<html:div class="datetime-input-box-wrapper"
xbl:inherits="context,disabled,readonly">
- <html:span>
+ <html:span class="datetime-input-edit-wrapper"
+ anonid="edit-wrapper">
<html:input anonid="input-one"
class="textbox-input datetime-input numeric"
size="2" maxlength="2"
@@ -980,9 +1045,8 @@
xbl:inherits="disabled,readonly,tabindex"/>
</html:span>
- <html:button class="datetime-reset-button" anoid="reset-button"
- tabindex="-1" xbl:inherits="disabled"
- onclick="document.getBindingParent(this).clearInputFields(false);"/>
+ <html:button class="datetime-reset-button" anonid="reset-button"
+ tabindex="-1" xbl:inherits="disabled"/>
</html:div>
</content>
@@ -997,6 +1061,9 @@
this.mStep = this.mInputElement.step;
this.mIsPickerOpen = false;
+ this.mResetButton =
+ document.getAnonymousElementByAttribute(this, "anonid", "reset-button");
+
this.EVENTS.forEach((eventName) => {
this.addEventListener(eventName, this, { mozSystemGroup: true });
});
@@ -1005,6 +1072,9 @@
capture: true,
mozSystemGroup: true
});
+ // This is to close the picker when input element blurs.
+ this.mInputElement.addEventListener("blur", this,
+ { mozSystemGroup: true });
]]>
</constructor>
@@ -1025,7 +1095,7 @@
<property name="EVENTS" readonly="true">
<getter>
<![CDATA[
- return ["click", "focus", "blur", "copy", "cut", "paste"];
+ return ["click", "focus", "blur", "copy", "cut", "paste", "mousedown"];
]]>
</getter>
</property>
@@ -1041,6 +1111,18 @@
</body>
</method>
+ <method name="updateResetButtonVisibility">
+ <body>
+ <![CDATA[
+ if (this.isAnyValueAvailable(false)) {
+ this.mResetButton.style.visibility = "visible";
+ } else {
+ this.mResetButton.style.visibility = "hidden";
+ }
+ ]]>
+ </body>
+ </method>
+
<method name="focusInnerTextBox">
<body>
<![CDATA[
@@ -1164,10 +1246,16 @@
</body>
</method>
+ <method name="isAnyValueAvailable">
+ <body>
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+ </body>
+ </method>
+
<method name="notifyPicker">
<body>
<![CDATA[
- if (this.mIsPickerOpen && this.isValueAvailable()) {
+ if (this.mIsPickerOpen && this.isAnyValueAvailable(true)) {
this.mInputElement.updateDateTimePicker(this.getCurrentValue());
}
]]>
@@ -1213,6 +1301,12 @@
this.onBlur(aEvent);
break;
}
+ case "mousedown": {
+ if (aEvent.originalTarget == this.mResetButton) {
+ aEvent.preventDefault();
+ }
+ break;
+ }
case "copy":
case "cut":
case "paste": {
@@ -1245,7 +1339,12 @@
<parameter name="aEvent"/>
<body>
<![CDATA[
- this.log("onBlur originalTarget: " + aEvent.originalTarget);
+ this.log("onBlur originalTarget: " + aEvent.originalTarget +
+ " target: " + aEvent.target);
+
+ if (aEvent.target == this.mInputElement && this.mIsPickerOpen) {
+ this.mInputElement.closeDateTimePicker();
+ }
let target = aEvent.originalTarget;
target.setAttribute("typeBuffer", "");
@@ -1261,16 +1360,23 @@
this.log("onKeyPress key: " + aEvent.key);
switch (aEvent.key) {
- // Close picker on Enter or Space key.
+ // Close picker on Enter, Escape or Space key.
case "Enter":
+ case "Escape":
case " ": {
- this.mInputElement.closeDateTimePicker();
- aEvent.preventDefault();
+ if (this.mIsPickerOpen) {
+ this.mInputElement.closeDateTimePicker();
+ aEvent.preventDefault();
+ }
break;
}
case "Backspace": {
let targetField = aEvent.originalTarget;
+ targetField.value = "";
targetField.setAttribute("typeBuffer", "");
+ this.updateResetButtonVisibility();
+ this.setInputValueFromFields();
+ aEvent.preventDefault();
break;
}
case "ArrowRight":
@@ -1312,12 +1418,14 @@
// XXX: .originalTarget is not expected.
// When clicking on one of the inner text boxes, the .originalTarget is
// a HTMLDivElement and when clicking on the reset button, it's a
- // HTMLButtonElement but it's not equal to our reset-button.
+ // HTMLButtonElement.
if (aEvent.defaultPrevented || this.isDisabled() || this.isReadonly()) {
return;
}
- if (!(aEvent.originalTarget instanceof HTMLButtonElement)) {
+ if (aEvent.originalTarget == this.mResetButton) {
+ this.clearInputFields(false);
+ } else if (!this.mIsPickerOpen) {
this.mInputElement.openDateTimePicker(this.getCurrentValue());
}
]]>