mirror of
https://github.com/ManchildProductions/UXP-Fixed.git
synced 2026-05-27 20:08:33 +00:00
808 lines
25 KiB
XML
808 lines
25 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
- 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/. -->
|
|
|
|
<bindings id="datetimeboxBindings"
|
|
xmlns="http://www.mozilla.org/xbl"
|
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
xmlns:xbl="http://www.mozilla.org/xbl">
|
|
|
|
<binding id="time-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 1301312 - localization for input type=time input.
|
|
this.mHour12 = true;
|
|
this.mAMIndicator = "AM";
|
|
this.mPMIndicator = "PM";
|
|
this.mPlaceHolder = "--";
|
|
this.mSeparatorText = ":";
|
|
this.mMillisecSeparatorText = ".";
|
|
this.mMaxLength = 2;
|
|
this.mMillisecMaxLength = 3;
|
|
this.mDefaultStep = 60 * 1000; // in milliseconds
|
|
|
|
this.mMinHourInHour12 = 1;
|
|
this.mMaxHourInHour12 = 12;
|
|
this.mMinMinute = 0;
|
|
this.mMaxMinute = 59;
|
|
this.mMinSecond = 0;
|
|
this.mMaxSecond = 59;
|
|
this.mMinMillisecond = 0;
|
|
this.mMaxMillisecond = 999;
|
|
|
|
this.mHourPageUpDownInterval = 3;
|
|
this.mMinSecPageUpDownInterval = 10;
|
|
|
|
this.mHourField =
|
|
document.getAnonymousElementByAttribute(this, "anonid", "input-one");
|
|
this.mHourField.setAttribute("typeBuffer", "");
|
|
this.mMinuteField =
|
|
document.getAnonymousElementByAttribute(this, "anonid", "input-two");
|
|
this.mMinuteField.setAttribute("typeBuffer", "");
|
|
this.mDayPeriodField =
|
|
document.getAnonymousElementByAttribute(this, "anonid", "input-three");
|
|
this.mDayPeriodField.classList.remove("numeric");
|
|
|
|
this.mHourField.placeholder = this.mPlaceHolder;
|
|
this.mMinuteField.placeholder = this.mPlaceHolder;
|
|
this.mDayPeriodField.placeholder = this.mPlaceHolder;
|
|
|
|
this.mHourField.setAttribute("min", this.mMinHourInHour12);
|
|
this.mHourField.setAttribute("max", this.mMaxHourInHour12);
|
|
this.mMinuteField.setAttribute("min", this.mMinMinute);
|
|
this.mMinuteField.setAttribute("max", this.mMaxMinute);
|
|
|
|
this.mMinuteSeparator =
|
|
document.getAnonymousElementByAttribute(this, "anonid", "sep-first");
|
|
this.mMinuteSeparator.textContent = this.mSeparatorText;
|
|
this.mSpaceSeparator =
|
|
document.getAnonymousElementByAttribute(this, "anonid", "sep-second");
|
|
// space between time and am/pm field
|
|
this.mSpaceSeparator.textContent = " ";
|
|
|
|
this.mSecondSeparator = null;
|
|
this.mSecondField = null;
|
|
this.mMillisecSeparator = null;
|
|
this.mMillisecField = null;
|
|
|
|
if (this.mInputElement.value) {
|
|
this.setFieldsFromInputValue();
|
|
}
|
|
]]>
|
|
</constructor>
|
|
|
|
<method name="insertSeparator">
|
|
<parameter name="aSeparatorText"/>
|
|
<body>
|
|
<![CDATA[
|
|
let container = this.mHourField.parentNode;
|
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
|
|
let separator = document.createElementNS(HTML_NS, "span");
|
|
separator.textContent = aSeparatorText;
|
|
separator.setAttribute("class", "datetime-separator");
|
|
container.insertBefore(separator, this.mSpaceSeparator);
|
|
|
|
return separator;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="insertAdditionalField">
|
|
<parameter name="aPlaceHolder"/>
|
|
<parameter name="aMin"/>
|
|
<parameter name="aMax"/>
|
|
<parameter name="aSize"/>
|
|
<parameter name="aMaxLength"/>
|
|
<body>
|
|
<![CDATA[
|
|
let container = this.mHourField.parentNode;
|
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
|
|
let field = document.createElementNS(HTML_NS, "input");
|
|
field.classList.add("textbox-input", "datetime-input", "numeric");
|
|
field.setAttribute("size", aSize);
|
|
field.setAttribute("maxlength", aMaxLength);
|
|
field.setAttribute("min", aMin);
|
|
field.setAttribute("max", aMax);
|
|
field.setAttribute("typeBuffer", "");
|
|
field.disabled = this.mInputElement.disabled;
|
|
field.readOnly = this.mInputElement.readOnly;
|
|
field.tabIndex = this.mInputElement.tabIndex;
|
|
field.placeholder = aPlaceHolder;
|
|
container.insertBefore(field, this.mSpaceSeparator);
|
|
|
|
return field;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setFieldsFromInputValue">
|
|
<body>
|
|
<![CDATA[
|
|
let value = this.mInputElement.value;
|
|
if (!value) {
|
|
this.clearInputFields(true);
|
|
return;
|
|
}
|
|
|
|
this.log("setFieldsFromInputValue: " + value);
|
|
let [hour, minute, second] = value.split(':');
|
|
|
|
this.setFieldValue(this.mHourField, hour);
|
|
this.setFieldValue(this.mMinuteField, minute);
|
|
if (this.mHour12) {
|
|
this.mDayPeriodField.value = (hour >= this.mMaxHourInHour12) ?
|
|
this.mPMIndicator : this.mAMIndicator;
|
|
}
|
|
|
|
if (!this.isEmpty(second)) {
|
|
let index = second.indexOf(".");
|
|
let millisecond;
|
|
if (index != -1) {
|
|
millisecond = second.substring(index + 1);
|
|
second = second.substring(0, index);
|
|
}
|
|
|
|
if (!this.mSecondField) {
|
|
this.mSecondSeparator = this.insertSeparator(this.mSeparatorText);
|
|
this.mSecondField = this.insertAdditionalField(this.mPlaceHolder,
|
|
this.mMinSecond, this.mMaxSecond, this.mMaxLength,
|
|
this.mMaxLength);
|
|
}
|
|
this.setFieldValue(this.mSecondField, second);
|
|
|
|
if (!this.isEmpty(millisecond)) {
|
|
if (!this.mMillisecField) {
|
|
this.mMillisecSeparator = this.insertSeparator(
|
|
this.mMillisecSeparatorText);
|
|
this.mMillisecField = this.insertAdditionalField(
|
|
this.mPlaceHolder, this.mMinMillisecond, this.mMaxMillisecond,
|
|
this.mMillisecMaxLength, this.mMillisecMaxLength);
|
|
}
|
|
this.setFieldValue(this.mMillisecField, millisecond);
|
|
} else if (this.mMillisecField) {
|
|
this.mMillisecField.remove();
|
|
this.mMillisecField = null;
|
|
|
|
this.mMillisecSeparator.remove();
|
|
this.mMillisecSeparator = null;
|
|
}
|
|
} else {
|
|
if (this.mSecondField) {
|
|
this.mSecondField.remove();
|
|
this.mSecondField = null;
|
|
|
|
this.mSecondSeparator.remove();
|
|
this.mSecondSeparator = null;
|
|
}
|
|
|
|
if (this.mMillisecField) {
|
|
this.mMillisecField.remove();
|
|
this.mMillisecField = null;
|
|
|
|
this.mMillisecSeparator.remove();
|
|
this.mMillisecSeparator = null;
|
|
}
|
|
}
|
|
this.notifyPicker();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setInputValueFromFields">
|
|
<body>
|
|
<![CDATA[
|
|
if (this.isEmpty(this.mHourField.value) ||
|
|
this.isEmpty(this.mMinuteField.value) ||
|
|
(this.mDayPeriodField && this.isEmpty(this.mDayPeriodField.value)) ||
|
|
(this.mSecondField && this.isEmpty(this.mSecondField.value)) ||
|
|
(this.mMillisecField && this.isEmpty(this.mMillisecField.value))) {
|
|
// 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 hour = Number(this.mHourField.value);
|
|
if (this.mHour12) {
|
|
let dayPeriod = this.mDayPeriodField.value;
|
|
if (dayPeriod == this.mPMIndicator &&
|
|
hour < this.mMaxHourInHour12) {
|
|
hour += this.mMaxHourInHour12;
|
|
} else if (dayPeriod == this.mAMIndicator &&
|
|
hour == this.mMaxHourInHour12) {
|
|
hour = 0;
|
|
}
|
|
}
|
|
|
|
hour = (hour < 10) ? ("0" + hour) : hour;
|
|
|
|
let time = hour + ":" + this.mMinuteField.value;
|
|
if (this.mSecondField) {
|
|
time += ":" + this.mSecondField.value;
|
|
}
|
|
|
|
if (this.mMillisecField) {
|
|
time += "." + this.mMillisecField.value;
|
|
}
|
|
|
|
this.log("setInputValueFromFields: " + time);
|
|
this.mInputElement.setUserInput(time);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setFieldsFromPicker">
|
|
<parameter name="aValue"/>
|
|
<body>
|
|
<![CDATA[
|
|
let hour = aValue.hour;
|
|
let minute = aValue.minute;
|
|
this.log("setFieldsFromPicker: " + hour + ":" + minute);
|
|
|
|
if (!this.isEmpty(hour)) {
|
|
this.setFieldValue(this.mHourField, hour);
|
|
if (this.mHour12) {
|
|
this.mDayPeriodField.value =
|
|
(hour >= this.mMaxHourInHour12) ? this.mPMIndicator
|
|
: this.mAMIndicator;
|
|
}
|
|
}
|
|
|
|
if (!this.isEmpty(minute)) {
|
|
this.setFieldValue(this.mMinuteField, minute);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="clearInputFields">
|
|
<parameter name="aFromInputElement"/>
|
|
<body>
|
|
<![CDATA[
|
|
this.log("clearInputFields");
|
|
|
|
if (this.isDisabled() || this.isReadonly()) {
|
|
return;
|
|
}
|
|
|
|
if (this.mHourField && !this.mHourField.disabled &&
|
|
!this.mHourField.readOnly) {
|
|
this.mHourField.value = "";
|
|
}
|
|
|
|
if (this.mMinuteField && !this.mMinuteField.disabled &&
|
|
!this.mMinuteField.readOnly) {
|
|
this.mMinuteField.value = "";
|
|
}
|
|
|
|
if (this.mSecondField && !this.mSecondField.disabled &&
|
|
!this.mSecondField.readOnly) {
|
|
this.mSecondField.value = "";
|
|
}
|
|
|
|
if (this.mMillisecField && !this.mMillisecField.disabled &&
|
|
!this.mMillisecField.readOnly) {
|
|
this.mMillisecField.value = "";
|
|
}
|
|
|
|
if (this.mDayPeriodField && !this.mDayPeriodField.disabled &&
|
|
!this.mDayPeriodField.readOnly) {
|
|
this.mDayPeriodField.value = "";
|
|
}
|
|
|
|
if (!aFromInputElement) {
|
|
this.mInputElement.setUserInput("");
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="incrementFieldValue">
|
|
<parameter name="aTargetField"/>
|
|
<parameter name="aTimes"/>
|
|
<body>
|
|
<![CDATA[
|
|
let value;
|
|
|
|
// Use current time if field is empty.
|
|
if (this.isEmpty(aTargetField.value)) {
|
|
let now = new Date();
|
|
|
|
if (aTargetField == this.mHourField) {
|
|
value = now.getHours() % this.mMaxHourInHour12 ||
|
|
this.mMaxHourInHour12;
|
|
} else if (aTargetField == this.mMinuteField) {
|
|
value = now.getMinutes();
|
|
} else if (aTargetField == this.mSecondField) {
|
|
value = now.getSeconds();
|
|
} else if (aTargetField == this.mMillisecField) {
|
|
value = now.getMilliseconds();
|
|
} else {
|
|
this.log("Field not supported in incrementFieldValue.");
|
|
return;
|
|
}
|
|
} else {
|
|
value = Number(aTargetField.value);
|
|
}
|
|
|
|
let min = aTargetField.getAttribute("min");
|
|
let max = aTargetField.getAttribute("max");
|
|
|
|
value += 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;
|
|
|
|
if (this.mDayPeriodField &&
|
|
targetField == this.mDayPeriodField) {
|
|
// Home/End key does nothing on AM/PM field.
|
|
if (key == "Home" || key == "End") {
|
|
return;
|
|
}
|
|
|
|
this.mDayPeriodField.value =
|
|
this.mDayPeriodField.value == this.mAMIndicator ?
|
|
this.mPMIndicator : this.mAMIndicator;
|
|
this.mDayPeriodField.select();
|
|
this.setInputValueFromFields();
|
|
return;
|
|
}
|
|
|
|
switch (key) {
|
|
case "ArrowUp":
|
|
this.incrementFieldValue(targetField, 1);
|
|
break;
|
|
case "ArrowDown":
|
|
this.incrementFieldValue(targetField, -1);
|
|
break;
|
|
case "PageUp":
|
|
this.incrementFieldValue(targetField,
|
|
targetField == this.mHourField ? this.mHourPageUpDownInterval
|
|
: this.mMinSecPageUpDownInterval);
|
|
break;
|
|
case "PageDown":
|
|
this.incrementFieldValue(targetField,
|
|
targetField == this.mHourField ? (0 - this.mHourPageUpDownInterval)
|
|
: (0 - this.mMinSecPageUpDownInterval));
|
|
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="handleKeypress">
|
|
<parameter name="aEvent"/>
|
|
<body>
|
|
<![CDATA[
|
|
if (this.isDisabled() || this.isReadonly()) {
|
|
return;
|
|
}
|
|
|
|
let targetField = aEvent.originalTarget;
|
|
let key = aEvent.key;
|
|
|
|
if (this.mDayPeriodField &&
|
|
targetField == this.mDayPeriodField) {
|
|
if (key == "a" || key == "A") {
|
|
this.mDayPeriodField.value = this.mAMIndicator;
|
|
this.mDayPeriodField.select();
|
|
} else if (key == "p" || key == "P") {
|
|
this.mDayPeriodField.value = this.mPMIndicator;
|
|
this.mDayPeriodField.select();
|
|
}
|
|
return;
|
|
}
|
|
|
|
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="setFieldValue">
|
|
<parameter name="aField"/>
|
|
<parameter name="aValue"/>
|
|
<body>
|
|
<![CDATA[
|
|
let value = Number(aValue);
|
|
if (isNaN(value)) {
|
|
this.log("NaN on setFieldValue!");
|
|
return;
|
|
}
|
|
|
|
if (aField.maxLength == this.mMaxLength) { // For hour, minute and second
|
|
if (aField == this.mHourField && this.mHour12) {
|
|
value = (value > this.mMaxHourInHour12) ?
|
|
value - this.mMaxHourInHour12 : value;
|
|
if (aValue == "00") {
|
|
value = this.mMaxHourInHour12;
|
|
}
|
|
}
|
|
// prepend zero
|
|
if (value < 10) {
|
|
value = "0" + value;
|
|
}
|
|
} else if (aField.maxLength == this.mMillisecMaxLength) {
|
|
// prepend zeroes
|
|
if (value < 10) {
|
|
value = "00" + value;
|
|
} else if (value < 100) {
|
|
value = "0" + value;
|
|
}
|
|
}
|
|
|
|
aField.value = value;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="isValueAvailable">
|
|
<body>
|
|
<![CDATA[
|
|
// Picker only cares about hour:minute.
|
|
return !this.isEmpty(this.mHourField.value) ||
|
|
!this.isEmpty(this.mMinuteField.value);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="getCurrentValue">
|
|
<body>
|
|
<![CDATA[
|
|
let hour;
|
|
if (!this.isEmpty(this.mHourField.value)) {
|
|
hour = Number(this.mHourField.value);
|
|
if (this.mHour12) {
|
|
let dayPeriod = this.mDayPeriodField.value;
|
|
if (dayPeriod == this.mPMIndicator &&
|
|
hour < this.mMaxHourInHour12) {
|
|
hour += this.mMaxHourInHour12;
|
|
} else if (dayPeriod == this.mAMIndicator &&
|
|
hour == this.mMaxHourInHour12) {
|
|
hour = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
let minute;
|
|
if (!this.isEmpty(this.mMinuteField.value)) {
|
|
minute = Number(this.mMinuteField.value);
|
|
}
|
|
|
|
// Picker only needs hour/minute.
|
|
let time = { hour, minute };
|
|
|
|
this.log("getCurrentValue: " + JSON.stringify(time));
|
|
return time;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
</implementation>
|
|
</binding>
|
|
|
|
<binding id="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>
|
|
|
|
<content>
|
|
<html:div class="datetime-input-box-wrapper"
|
|
xbl:inherits="context,disabled,readonly">
|
|
<html:span>
|
|
<html:input anonid="input-one"
|
|
class="textbox-input datetime-input numeric"
|
|
size="2" maxlength="2"
|
|
xbl:inherits="disabled,readonly,tabindex"/>
|
|
<html:span anonid="sep-first" class="datetime-separator"></html:span>
|
|
<html:input anonid="input-two"
|
|
class="textbox-input datetime-input numeric"
|
|
size="2" maxlength="2"
|
|
xbl:inherits="disabled,readonly,tabindex"/>
|
|
<html:span anonid="sep-second" class="datetime-separator"></html:span>
|
|
<html:input anonid="input-three"
|
|
class="textbox-input datetime-input numeric"
|
|
size="2" maxlength="2"
|
|
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:div>
|
|
</content>
|
|
|
|
<implementation implements="nsIDateTimeInputArea">
|
|
<constructor>
|
|
<![CDATA[
|
|
this.DEBUG = false;
|
|
this.mInputElement = this.parentNode;
|
|
|
|
this.mMin = this.mInputElement.min;
|
|
this.mMax = this.mInputElement.max;
|
|
this.mStep = this.mInputElement.step;
|
|
this.mIsPickerOpen = false;
|
|
]]>
|
|
</constructor>
|
|
|
|
<method name="log">
|
|
<parameter name="aMsg"/>
|
|
<body>
|
|
<![CDATA[
|
|
if (this.DEBUG) {
|
|
dump("[DateTimeBox] " + aMsg + "\n");
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="focusInnerTextBox">
|
|
<body>
|
|
<![CDATA[
|
|
this.log("focusInnerTextBox");
|
|
document.getAnonymousElementByAttribute(this, "anonid", "input-one").focus();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="blurInnerTextBox">
|
|
<body>
|
|
<![CDATA[
|
|
this.log("blurInnerTextBox");
|
|
if (this.mLastFocusedField) {
|
|
this.mLastFocusedField.blur();
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="notifyInputElementValueChanged">
|
|
<body>
|
|
<![CDATA[
|
|
this.log("inputElementValueChanged");
|
|
this.setFieldsFromInputValue();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setValueFromPicker">
|
|
<parameter name="aValue"/>
|
|
<body>
|
|
<![CDATA[
|
|
this.setFieldsFromPicker(aValue);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="advanceToNextField">
|
|
<parameter name="aReverse"/>
|
|
<body>
|
|
<![CDATA[
|
|
this.log("advanceToNextField");
|
|
|
|
let focusedInput = this.mLastFocusedField;
|
|
let next = aReverse ? focusedInput.previousElementSibling
|
|
: focusedInput.nextElementSibling;
|
|
if (!next && !aReverse) {
|
|
this.setInputValueFromFields();
|
|
return;
|
|
}
|
|
|
|
while (next) {
|
|
if (next.type == "text" && !next.disabled) {
|
|
next.focus();
|
|
break;
|
|
}
|
|
next = aReverse ? next.previousElementSibling
|
|
: next.nextElementSibling;
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setPickerState">
|
|
<parameter name="aIsOpen"/>
|
|
<body>
|
|
<![CDATA[
|
|
this.log("picker is now " + (aIsOpen ? "opened" : "closed"));
|
|
this.mIsPickerOpen = aIsOpen;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="isEmpty">
|
|
<parameter name="aValue"/>
|
|
<body>
|
|
return (aValue == undefined || 0 === aValue.length);
|
|
</body>
|
|
</method>
|
|
|
|
<method name="clearInputFields">
|
|
<body>
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setFieldsFromInputValue">
|
|
<body>
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setInputValueFromFields">
|
|
<body>
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
</body>
|
|
</method>
|
|
|
|
<method name="setFieldsFromPicker">
|
|
<body>
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
</body>
|
|
</method>
|
|
|
|
<method name="handleKeypress">
|
|
<body>
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
</body>
|
|
</method>
|
|
|
|
<method name="handleKeyboardNav">
|
|
<body>
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
</body>
|
|
</method>
|
|
|
|
<method name="notifyPicker">
|
|
<body>
|
|
<![CDATA[
|
|
if (this.mIsPickerOpen && this.isValueAvailable()) {
|
|
this.mInputElement.updateDateTimePicker(this.getCurrentValue());
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="isDisabled">
|
|
<body>
|
|
<![CDATA[
|
|
return this.hasAttribute("disabled");
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="isReadonly">
|
|
<body>
|
|
<![CDATA[
|
|
return this.hasAttribute("readonly");
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
</implementation>
|
|
|
|
<handlers>
|
|
<handler event="focus">
|
|
<![CDATA[
|
|
this.log("focus on: " + event.originalTarget);
|
|
|
|
let target = event.originalTarget;
|
|
if (target.type == "text") {
|
|
this.mLastFocusedField = target;
|
|
target.select();
|
|
}
|
|
]]>
|
|
</handler>
|
|
|
|
<handler event="blur">
|
|
<![CDATA[
|
|
this.setInputValueFromFields();
|
|
]]>
|
|
</handler>
|
|
|
|
<handler event="click">
|
|
<![CDATA[
|
|
// 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.
|
|
this.log("click on: " + event.originalTarget);
|
|
if (event.defaultPrevented || this.isDisabled() || this.isReadonly()) {
|
|
return;
|
|
}
|
|
|
|
if (!(event.originalTarget instanceof HTMLButtonElement)) {
|
|
this.mInputElement.openDateTimePicker(this.getCurrentValue());
|
|
}
|
|
]]>
|
|
</handler>
|
|
|
|
<handler event="keypress" phase="capturing">
|
|
<![CDATA[
|
|
let key = event.key;
|
|
this.log("keypress: " + key);
|
|
|
|
if (key == "Backspace" || key == "Tab") {
|
|
return;
|
|
}
|
|
|
|
if (key == "Enter" || key == " ") {
|
|
// Close picker on Enter and Space.
|
|
this.mInputElement.closeDateTimePicker();
|
|
}
|
|
|
|
if (key == "ArrowUp" || key == "ArrowDown" ||
|
|
key == "PageUp" || key == "PageDown" ||
|
|
key == "Home" || key == "End") {
|
|
this.handleKeyboardNav(event);
|
|
} else if (key == "ArrowRight" || key == "ArrowLeft") {
|
|
this.advanceToNextField((key == "ArrowRight" ? false : true));
|
|
} else {
|
|
this.handleKeypress(event);
|
|
}
|
|
|
|
event.preventDefault();
|
|
]]>
|
|
</handler>
|
|
</handlers>
|
|
</binding>
|
|
|
|
</bindings>
|