author | Jessica Jong <jjong@mozilla.com> |
Tue, 24 Jan 2017 17:19:00 +0100 | |
changeset 331002 | f17e441ce4d05bb69a98a5088d7d8f0e3b4c8e0c |
parent 331001 | 57bd56bce11aa7612cc6978ad0a1447103c04b54 |
child 331003 | f25c2fd8740b383c1fa5524222c99e2c87518e13 |
push id | 31258 |
push user | kwierso@gmail.com |
push date | Thu, 26 Jan 2017 00:56:03 +0000 |
treeherder | mozilla-central@52a34f9a6cf1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mconley |
bugs | 1318317 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/toolkit/content/widgets/datetimebox.xml +++ b/toolkit/content/widgets/datetimebox.xml @@ -71,16 +71,17 @@ this.mDaySeparator.textContent = this.mSeparatorText; this.mYearSeparator = document.getAnonymousElementByAttribute(this, "anonid", "sep-second"); this.mYearSeparator.textContent = this.mSeparatorText; if (this.mInputElement.value) { this.setFieldsFromInputValue(); } + this.updateResetButtonVisibility(); ]]> </constructor> <method name="clearInputFields"> <parameter name="aFromInputElement"/> <body> <![CDATA[ this.log("clearInputFields"); @@ -105,16 +106,18 @@ !this.mYearField.readOnly) { this.mYearField.value = ""; this.mYearField.setAttribute("typeBuffer", ""); } if (!aFromInputElement) { this.mInputElement.setUserInput(""); } + + this.updateResetButtonVisibility(); ]]> </body> </method> <method name="setFieldsFromInputValue"> <body> <![CDATA[ let value = this.mInputElement.value; @@ -165,16 +168,21 @@ return false; ]]> </body> </method> <method name="setInputValueFromFields"> <body> <![CDATA[ + if (!this.isAnyValueAvailable(false)) { + this.mInputElement.setUserInput(""); + return; + } + 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; @@ -401,21 +409,23 @@ if (value.toString().length > this.mYearLength && value.toString().length <= this.mMaxYear.toString().length) { this.mYearField.size = value.toString().length; } } aField.value = value; + this.updateResetButtonVisibility(); ]]> </body> </method> - <method name="isValueAvailable"> + <method name="isAnyValueAvailable"> + <parameter name="aForPicker"/> <body> <![CDATA[ return !this.isEmpty(this.mMonthField.value) || !this.isEmpty(this.mDayField.value) || !this.isEmpty(this.mYearField.value); ]]> </body> </method> @@ -487,16 +497,17 @@ this.mSecondSeparator = null; this.mSecondField = null; this.mMillisecSeparator = null; this.mMillisecField = null; if (this.mInputElement.value) { this.setFieldsFromInputValue(); } + this.updateResetButtonVisibility(); ]]> </constructor> <method name="insertSeparator"> <parameter name="aSeparatorText"/> <body> <![CDATA[ let container = this.mHourField.parentNode; @@ -612,16 +623,21 @@ this.notifyPicker(); ]]> </body> </method> <method name="setInputValueFromFields"> <body> <![CDATA[ + if (!this.isAnyValueAvailable(false)) { + this.mInputElement.setUserInput(""); + return; + } + 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(). @@ -719,16 +735,18 @@ if (this.mDayPeriodField && !this.mDayPeriodField.disabled && !this.mDayPeriodField.readOnly) { this.mDayPeriodField.value = ""; } if (!aFromInputElement) { this.mInputElement.setUserInput(""); } + + this.updateResetButtonVisibility(); ]]> </body> </method> <method name="incrementFieldValue"> <parameter name="aTargetField"/> <parameter name="aTimes"/> <body> @@ -788,16 +806,17 @@ if (key == "Home" || key == "End") { return; } this.mDayPeriodField.value = this.mDayPeriodField.value == this.mAMIndicator ? this.mPMIndicator : this.mAMIndicator; this.mDayPeriodField.select(); + this.updateResetButtonVisibility(); this.setInputValueFromFields(); return; } switch (key) { case "ArrowUp": this.incrementFieldValue(targetField, 1); break; @@ -845,16 +864,17 @@ 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(); } + this.updateResetButtonVisibility(); return; } if (targetField.classList.contains("numeric") && key.match(/[0-9]/)) { let buffer = targetField.getAttribute("typeBuffer") || ""; buffer = buffer.concat(key); this.setFieldValue(targetField, buffer); @@ -900,26 +920,40 @@ if (value < 10) { value = "00" + value; } else if (value < 100) { value = "0" + value; } } 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> <method name="getCurrentValue"> <body> <![CDATA[ let hour; @@ -975,33 +1009,35 @@ 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:button class="datetime-reset-button" anonid="reset-button" + tabindex="-1" xbl:inherits="disabled"/> </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; + this.mResetButton = + document.getAnonymousElementByAttribute(this, "anonid", "reset-button"); + 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 }); @@ -1036,16 +1072,28 @@ <![CDATA[ if (this.DEBUG) { dump("[DateTimeBox] " + aMsg + "\n"); } ]]> </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[ this.log("focusInnerTextBox"); document.getAnonymousElementByAttribute(this, "anonid", "input-one").focus(); ]]> </body> </method> @@ -1159,20 +1207,26 @@ </method> <method name="getCurrentValue"> <body> throw Components.results.NS_ERROR_NOT_IMPLEMENTED; </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()); } ]]> </body> </method> <method name="isDisabled"> <body> @@ -1265,17 +1319,21 @@ case "Enter": case " ": { 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": case "ArrowLeft": { this.advanceToNextField(aEvent.key == "ArrowRight" ? false : true); aEvent.preventDefault(); break; } @@ -1307,22 +1365,24 @@ <parameter name="aEvent"/> <body> <![CDATA[ this.log("onClick originalTarget: " + aEvent.originalTarget); // 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 { this.mInputElement.openDateTimePicker(this.getCurrentValue()); } ]]> </body> </method> </implementation> </binding>