Bug 1372369 - Part 1: Update input element's value when all fields are available and let DOM HTMLInputElement sanitize it. r=smaug
authorJessica Jong <jjong@mozilla.com>
Fri, 16 Jun 2017 02:09:00 -0400
changeset 596640 197dee6bc4767e293779a5a002a015413ba5bc50
parent 596639 dceb915d3c4008af14d691a622216d2986104033
child 596641 b9a984aa8176e15694b5a0d193f48022acada58a
push id64704
push userbmo:rail@mozilla.com
push dateMon, 19 Jun 2017 15:14:27 +0000
reviewerssmaug
bugs1372369
milestone56.0a1
Bug 1372369 - Part 1: Update input element's value when all fields are available and let DOM HTMLInputElement sanitize it. r=smaug In this patch, we change it so that we always set the input element's value once all fields are available and let DOM HTMLInputElement sanitize it. The value after sanitization is not updated in the displayed input box, but may display an error message (this will be done in Part 2) if needed. Also, when any of the field's value is deleted, we will set input element's value back to the empty string, so that a value is not accidentally submitted. MozReview-Commit-ID: 9NAL8UlkoBK
dom/html/HTMLInputElement.cpp
toolkit/content/widgets/datetimebox.xml
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -3084,17 +3084,18 @@ HTMLInputElement::SetValueInternal(const
           }
         } else if (mType == NS_FORM_INPUT_RANGE) {
           nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame());
           if (frame) {
             frame->UpdateForValueChange();
           }
         } else if ((mType == NS_FORM_INPUT_TIME ||
                     mType == NS_FORM_INPUT_DATE) &&
-                   !IsExperimentalMobileType(mType)) {
+                   !IsExperimentalMobileType(mType) &&
+                   !(aFlags & nsTextEditorState::eSetValue_BySetUserInput)) {
           nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
           if (frame) {
             frame->UpdateInputBoxValue();
           }
         }
         if (mDoneCreating) {
           OnValueChanged(/* aNotify = */ true,
                          /* aWasInteractiveUserChange = */ false);
--- a/toolkit/content/widgets/datetimebox.xml
+++ b/toolkit/content/widgets/datetimebox.xml
@@ -149,89 +149,46 @@
           this.setFieldValue(this.mMonthField, month);
           this.setFieldValue(this.mDayField, day);
 
           this.notifyPicker();
         ]]>
         </body>
       </method>
 
-      <method name="getDaysInMonth">
-        <parameter name="aMonth"/>
-        <parameter name="aYear"/>
-        <body>
-        <![CDATA[
-          // Javascript's month is 0-based, so this means last day of the
-          // previous month.
-          return new Date(aYear, aMonth, 0).getDate();
-        ]]>
-        </body>
-      </method>
-
-      <method name="isFieldInvalid">
-        <parameter name="aField"/>
-        <body>
-          <![CDATA[
-            let value = this.getFieldValue(aField);
-            if (this.isEmpty(value)) {
-              return true;
-            }
-
-            let min = Number(aField.getAttribute("min"));
-            let max = Number(aField.getAttribute("max"));
-
-            if (value < min || value > max) {
-              return true;
-            }
-
-            return false;
-          ]]>
-        </body>
-      </method>
-
       <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;
-          }
+          let { year, month, day } = this.getCurrentValue();
 
-          if (this.isFieldInvalid(this.mYearField) ||
-              this.isFieldInvalid(this.mMonthField) ||
-              this.isFieldInvalid(this.mDayField)) {
+          if (this.isEmpty(year) || this.isEmpty(month) || this.isEmpty(day)) {
+            // Clear input element's value if any of the field has been cleared.
+            if (this.mInputElement.value) {
+              this.mInputElement.setUserInput("");
+            }
             // 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().
+            // changed.
             this.notifyPicker();
             return;
           }
 
-          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("-");
 
           if (date == this.mInputElement.value) {
             return;
           }
 
           this.log("setInputValueFromFields: " + date);
+          this.notifyPicker();
           this.mInputElement.setUserInput(date);
         ]]>
         </body>
       </method>
 
       <method name="setFieldsFromPicker">
         <parameter name="aValue"/>
         <body>
@@ -701,30 +658,27 @@
           this.notifyPicker();
         ]]>
         </body>
       </method>
 
       <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;
-          }
-
           let { hour, minute, second, millisecond } = this.getCurrentValue();
           let dayPeriod = this.getDayPeriodValue();
 
           if (this.isEmpty(hour) || this.isEmpty(minute) ||
               (this.mDayPeriodField && this.isEmpty(dayPeriod)) ||
               (this.mSecondField && this.isEmpty(second)) ||
               (this.mMillisecField && this.isEmpty(millisecond))) {
+            // Clear input element's value if any of the field has been cleared.
+            if (this.mInputElement.value) {
+              this.mInputElement.setUserInput("");
+            }
             // 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;
           }
 
           // Convert to a valid time string according to:
@@ -754,16 +708,17 @@
             time += "." + millisecond;
           }
 
           if (time == this.mInputElement.value) {
             return;
           }
 
           this.log("setInputValueFromFields: " + time);
+          this.notifyPicker();
           this.mInputElement.setUserInput(time);
         ]]>
         </body>
       </method>
 
       <method name="setFieldsFromPicker">
         <parameter name="aValue"/>
         <body>