mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-16 12:17:34 +09:00
moebius#92: HTML - input - datetime
+ native in moebius: Bug 1317600: https://bugzilla.mozilla.org/show_bug.cgi?id=1317600 A note - not implemented: Bug 1282768: https://bugzilla.mozilla.org/show_bug.cgi?id=1282768 *.css: filter: url("chrome://global/skin/filters.svg#fill");, fill: Bug 1283385: https://bugzilla.mozilla.org/show_bug.cgi?id=1283385 Bug 1323109: https://bugzilla.mozilla.org/show_bug.cgi?id=1323109 Bug 1314544: https://bugzilla.mozilla.org/show_bug.cgi?id=1314544 Bug 1286182: https://bugzilla.mozilla.org/show_bug.cgi?id=1286182 Bug 1325922: https://bugzilla.mozilla.org/show_bug.cgi?id=1325922 A note - not implemented: Bug 1282768: https://bugzilla.mozilla.org/show_bug.cgi?id=1282768 *.css: filter: url("chrome://global/skin/filters.svg#fill");, fill: Bug 1320225: https://bugzilla.mozilla.org/show_bug.cgi?id=1320225 Bug 1341190: https://bugzilla.mozilla.org/show_bug.cgi?id=1341190
This commit is contained in:
parent
a807f7e6c0
commit
cac5c5adc7
34 changed files with 1267 additions and 248 deletions
|
|
@ -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());
|
||||
}
|
||||
]]>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue