From d8bcf2270ac4233bac34a9760b30d5d9b23901a2 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Feb 2018 14:41:19 +0100 Subject: [PATCH] Bug 1286182: Implement the layout for --- .../tests/mochitest/jsat/test_output.html | 9 - dom/html/HTMLInputElement.cpp | 23 +- dom/html/nsIFormControl.h | 2 +- dom/html/test/forms/mochitest.ini | 6 +- .../forms/test_input_date_key_events.html | 228 ++++++++++ .../forms/test_input_datetime_focus_blur.html | 28 +- ...test_input_datetime_focus_blur_events.html | 90 ++++ .../forms/test_input_datetime_tabindex.html | 47 +- .../test_input_time_focus_blur_events.html | 82 ---- .../forms/test_input_typing_sanitization.html | 28 ++ layout/base/nsCSSFrameConstructor.cpp | 4 +- layout/forms/nsDateTimeControlFrame.cpp | 3 +- layout/style/res/html.css | 5 + .../satchel/test/test_form_autocomplete.html | 12 +- toolkit/content/widgets/datetimebox.xml | 420 +++++++++++++++++- 15 files changed, 846 insertions(+), 141 deletions(-) create mode 100644 dom/html/test/forms/test_input_date_key_events.html create mode 100644 dom/html/test/forms/test_input_datetime_focus_blur_events.html delete mode 100644 dom/html/test/forms/test_input_time_focus_blur_events.html diff --git a/accessible/tests/mochitest/jsat/test_output.html b/accessible/tests/mochitest/jsat/test_output.html index ec2b289bea..5256426070 100644 --- a/accessible/tests/mochitest/jsat/test_output.html +++ b/accessible/tests/mochitest/jsat/test_output.html @@ -124,14 +124,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 "Peaches", {"string": "linkAbbr"}, "Plums", {"string": "linkAbbr"}, {"string": "listAbbr"}, {"string": "cellInfoAbbr", "args": [ 1, 1]}]] - }, { - accOrElmOrID: "date", - expectedUtterance: [[{"string": "textInputType_date"}, - {"string": "entry"}, "2011-09-29"], ["2011-09-29", - {"string": "textInputType_date"}, {"string": "entry"}]], - expectedBraille: [[{"string": "textInputType_date"}, - {"string": "entryAbbr"}, "2011-09-29"], ["2011-09-29", - {"string": "textInputType_date"}, {"string": "entryAbbr"}]] }, { accOrElmOrID: "email", expectedUtterance: [[{"string": "textInputType_email"}, @@ -619,7 +611,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 - diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index d46eccdbc0..e8a4af454c 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -2832,7 +2832,8 @@ HTMLInputElement::GetOwnerDateTimeControl() HTMLInputElement::FromContentOrNull( GetParent()->GetParent()->GetParent()->GetParent()); if (ownerDateTimeControl && - ownerDateTimeControl->mType == NS_FORM_INPUT_TIME) { + (ownerDateTimeControl->mType == NS_FORM_INPUT_TIME || + ownerDateTimeControl->mType == NS_FORM_INPUT_DATE)) { return ownerDateTimeControl; } } @@ -3282,7 +3283,8 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, uint32_t aFlags) if (frame) { frame->UpdateForValueChange(); } - } else if (mType == NS_FORM_INPUT_TIME && + } else if ((mType == NS_FORM_INPUT_TIME || + mType == NS_FORM_INPUT_DATE) && !IsExperimentalMobileType(mType)) { nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame()); if (frame) { @@ -3591,7 +3593,8 @@ HTMLInputElement::Blur(ErrorResult& aError) } } - if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType)) { + if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) && + !IsExperimentalMobileType(mType)) { nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame()); if (frame) { frame->HandleBlurEvent(); @@ -3618,7 +3621,8 @@ HTMLInputElement::Focus(ErrorResult& aError) } } - if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType)) { + if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) && + !IsExperimentalMobileType(mType)) { nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame()); if (frame) { frame->HandleFocusEvent(); @@ -3956,7 +3960,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - if (mType == NS_FORM_INPUT_TIME && + if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) && !IsExperimentalMobileType(mType) && aVisitor.mEvent->mMessage == eFocus && aVisitor.mEvent->mOriginalTarget == this) { @@ -4083,7 +4087,8 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) // Stop the event if the related target's first non-native ancestor is the // same as the original target's first non-native ancestor (we are moving // inside of the same element). - if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType) && + if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) && + !IsExperimentalMobileType(mType) && (aVisitor.mEvent->mMessage == eFocus || aVisitor.mEvent->mMessage == eFocusIn || aVisitor.mEvent->mMessage == eFocusOut || @@ -7161,13 +7166,15 @@ HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* if (mType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_NUMBER || - mType == NS_FORM_INPUT_TIME) { + mType == NS_FORM_INPUT_TIME || + mType == NS_FORM_INPUT_DATE) { if (aTabIndex) { // We only want our native anonymous child to be tabable to, not ourself. *aTabIndex = -1; } if (mType == NS_FORM_INPUT_NUMBER || - mType == NS_FORM_INPUT_TIME) { + mType == NS_FORM_INPUT_TIME || + mType == NS_FORM_INPUT_DATE) { *aIsFocusable = true; } else { *aIsFocusable = defaultFocusable; diff --git a/dom/html/nsIFormControl.h b/dom/html/nsIFormControl.h index aaa92146ce..e07f7c8293 100644 --- a/dom/html/nsIFormControl.h +++ b/dom/html/nsIFormControl.h @@ -270,8 +270,8 @@ nsIFormControl::IsSingleLineTextControl(bool aExcludePassword, uint32_t aType) #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) // On Android/B2G, date/time input appears as a normal text box. aType == NS_FORM_INPUT_TIME || -#endif aType == NS_FORM_INPUT_DATE || +#endif aType == NS_FORM_INPUT_MONTH || aType == NS_FORM_INPUT_WEEK || aType == NS_FORM_INPUT_DATETIME_LOCAL || diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini index 35955b189b..6fceefd981 100644 --- a/dom/html/test/forms/mochitest.ini +++ b/dom/html/test/forms/mochitest.ini @@ -30,8 +30,12 @@ skip-if = os == "android" # up/down arrow keys not supported on android skip-if = android_version == '18' # Android, bug 1147974 [test_input_color_picker_update.html] skip-if = android_version == '18' # Android, bug 1147974 +[test_input_date_key_events.html] +skip-if = os == "android" [test_input_datetime_focus_blur.html] skip-if = os == "android" +[test_input_datetime_focus_blur_events.html] +skip-if = os == "android" [test_input_datetime_tabindex.html] skip-if = os == "android" [test_input_defaultValue.html] @@ -61,8 +65,6 @@ skip-if = os == "android" [test_input_textarea_set_value_no_scroll.html] [test_input_time_key_events.html] skip-if = os == "android" -[test_input_time_focus_blur_events.html] -skip-if = os == "android" [test_input_types_pref.html] [test_input_typing_sanitization.html] [test_input_untrusted_key_events.html] diff --git a/dom/html/test/forms/test_input_date_key_events.html b/dom/html/test/forms/test_input_date_key_events.html new file mode 100644 index 0000000000..cd974e5057 --- /dev/null +++ b/dom/html/test/forms/test_input_date_key_events.html @@ -0,0 +1,228 @@ + + + + + Test key events for time control + + + + + + +Mozilla Bug 1286182 +

+
+ +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_focus_blur.html b/dom/html/test/forms/test_input_datetime_focus_blur.html index 5b8d95b25e..85f7b4bb4f 100644 --- a/dom/html/test/forms/test_input_datetime_focus_blur.html +++ b/dom/html/test/forms/test_input_datetime_focus_blur.html @@ -4,7 +4,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 --> - Test focus/blur behaviour for <input type='time'> + Test focus/blur behaviour for date/time input types @@ -12,7 +12,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 Mozilla Bug 1288591

- + +
 
 
diff --git a/dom/html/test/forms/test_input_datetime_focus_blur_events.html b/dom/html/test/forms/test_input_datetime_focus_blur_events.html new file mode 100644 index 0000000000..873dda627d --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_focus_blur_events.html @@ -0,0 +1,90 @@ + + + + +Test for Bug 1301306 + + + + + +Mozilla Bug 722599 +

+
+ + +
+
+
+
+ + diff --git a/dom/html/test/forms/test_input_datetime_tabindex.html b/dom/html/test/forms/test_input_datetime_tabindex.html index fb7c9b2f19..8023ccf9be 100644 --- a/dom/html/test/forms/test_input_datetime_tabindex.html +++ b/dom/html/test/forms/test_input_datetime_tabindex.html @@ -4,7 +4,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 --> - Test tabindex attribute for <input type='time'> + Test tabindex attribute for date/time input types @@ -16,13 +16,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 + + +
 
 
diff --git a/dom/html/test/forms/test_input_time_focus_blur_events.html b/dom/html/test/forms/test_input_time_focus_blur_events.html deleted file mode 100644 index 4837414774..0000000000 --- a/dom/html/test/forms/test_input_time_focus_blur_events.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -Test for Bug 1301306 - - - - - -Mozilla Bug 722599 -

-
- -
-
-
-
- - diff --git a/dom/html/test/forms/test_input_typing_sanitization.html b/dom/html/test/forms/test_input_typing_sanitization.html index 0896f19df8..eee300b33f 100644 --- a/dom/html/test/forms/test_input_typing_sanitization.html +++ b/dom/html/test/forms/test_input_typing_sanitization.html @@ -26,6 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=765772 * This test checks that when a user types in some input types, it will not be * in a state where the value will be un-sanitized and usable (by a script). */ +const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent); var input = document.getElementById('i'); var form = document.getElementById('f'); @@ -143,6 +144,7 @@ function runTest() ] }, { + mobileOnly: true, type: 'date', validData: [ '0001-01-01', @@ -160,6 +162,28 @@ function runTest() '1000-12-99', ] }, + { + mobileOnly: true, + type: 'time', + validData: [ + '00:00', + '09:09:00', + '08:23:23.1', + '21:43:56.12', + '23:12:45.100', + ], + invalidData: [ + '00:', + '00:00:', + '25:00', + '-00:00', + '00:00:00.', + '00:60', + '10:58:99', + ':19:10', + '23:08:09.1012', + ] + }, { type: 'month', validData: [ @@ -218,6 +242,10 @@ function runTest() for (test of data) { gCurrentTest = test; + if (gCurrentTest.mobileOnly && isDesktop) { + continue; + } + input.type = test.type; gValidData = test.validData; gInvalidData = test.invalidData; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index a118c38f93..f8c7f52a9e 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -3658,13 +3658,13 @@ nsCSSFrameConstructor::FindInputData(Element* aElement, nsCSSAnonBoxes::buttonContent) }, // TODO: this is temporary until a frame is written: bug 635240. SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame), - // TODO: this is temporary until a frame is written: bug 888320. - SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame), #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) // On Android/B2G, date/time input appears as a normal text box. SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewTextControlFrame), + SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame), #else SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewDateTimeControlFrame), + SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewDateTimeControlFrame), #endif // TODO: this is temporary until a frame is written: bug 888320 SIMPLE_INT_CREATE(NS_FORM_INPUT_MONTH, NS_NewTextControlFrame), diff --git a/layout/forms/nsDateTimeControlFrame.cpp b/layout/forms/nsDateTimeControlFrame.cpp index df2e43986b..fa22dcebac 100644 --- a/layout/forms/nsDateTimeControlFrame.cpp +++ b/layout/forms/nsDateTimeControlFrame.cpp @@ -372,7 +372,8 @@ nsDateTimeControlFrame::AttributeChanged(int32_t aNameSpaceID, auto contentAsInputElem = static_cast(mContent); // If script changed the 's type before setting these attributes // then we don't need to do anything since we are going to be reframed. - if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME) { + if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME || + contentAsInputElem->GetType() == NS_FORM_INPUT_DATE) { if (aAttribute == nsGkAtoms::value) { nsCOMPtr inputAreaContent = do_QueryInterface(mInputAreaContent); diff --git a/layout/style/res/html.css b/layout/style/res/html.css index a779461de9..bc3f082100 100644 --- a/layout/style/res/html.css +++ b/layout/style/res/html.css @@ -774,6 +774,11 @@ input[type="time"] > xul|datetimebox { -moz-binding: url("chrome://global/content/bindings/datetimebox.xml#time-input"); } +input[type="date"] > xul|datetimebox { + display: flex; + -moz-binding: url("chrome://global/content/bindings/datetimebox.xml#date-input"); +} + /* details & summary */ /* Need to revert Bug 1259889 Part 2 when removing details preference. */ @supports -moz-bool-pref("dom.details_element.enabled") { diff --git a/toolkit/components/satchel/test/test_form_autocomplete.html b/toolkit/components/satchel/test/test_form_autocomplete.html index 4cf09117a0..d2c22a3db0 100644 --- a/toolkit/components/satchel/test/test_form_autocomplete.html +++ b/toolkit/components/satchel/test/test_form_autocomplete.html @@ -172,7 +172,7 @@ function setupFormHistory(aCallback) { { op : "add", fieldname : "field8", value : "value" }, { op : "add", fieldname : "field9", value : "value" }, { op : "add", fieldname : "field10", value : "42" }, - { op : "add", fieldname : "field11", value : "2010-10-10" }, + { op : "add", fieldname : "field11", value : "2010-10-10" }, // not used, since type=date doesn't have autocomplete currently { op : "add", fieldname : "field12", value : "21:21" }, // not used, since type=time doesn't have autocomplete currently { op : "add", fieldname : "field13", value : "32" }, // not used, since type=range doesn't have a drop down menu { op : "add", fieldname : "field14", value : "#ffffff" }, // not used, since type=color doesn't have autocomplete currently @@ -899,15 +899,13 @@ function runTest() { input = $_(14, "field11"); restoreForm(); - expectPopup(); - doKey("down"); + waitForMenuChange(0); break; case 405: - checkMenuEntries(["2010-10-10"]); - doKey("down"); - doKey("return"); - checkForm("2010-10-10"); + checkMenuEntries([]); // type=date with it's own control frame does not + // have a drop down menu for now + checkForm(""); input = $_(15, "field12"); restoreForm(); diff --git a/toolkit/content/widgets/datetimebox.xml b/toolkit/content/widgets/datetimebox.xml index 21cc6c1bdc..677d3fc21b 100644 --- a/toolkit/content/widgets/datetimebox.xml +++ b/toolkit/content/widgets/datetimebox.xml @@ -10,6 +10,405 @@ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xbl="http://www.mozilla.org/xbl"> + + + + + + + + + + input box + this.mMonthPlaceHolder = "mm"; + this.mDayPlaceHolder = "dd"; + this.mYearPlaceHolder = "yyyy"; + this.mSeparatorText = "/"; + this.mMinMonth = 1; + this.mMaxMonth = 12; + this.mMinDay = 1; + this.mMaxDay = 31; + this.mMinYear = 1; + // Maximum year limited by ECMAScript date object range, year <= 275760. + this.mMaxYear = 275760; + this.mMonthDayLength = 2; + this.mYearLength = 4; + this.mMonthPageUpDownInterval = 3; + this.mDayPageUpDownInterval = 7; + this.mYearPageUpDownInterval = 10; + + // Default to en-US, month-day-year order. + this.mMonthField = + document.getAnonymousElementByAttribute(this, "anonid", "input-one"); + this.mDayField = + document.getAnonymousElementByAttribute(this, "anonid", "input-two"); + this.mYearField = + document.getAnonymousElementByAttribute(this, "anonid", "input-three"); + this.mYearField.size = this.mYearLength; + this.mYearField.maxLength = this.mMaxYear.toString().length; + + this.mMonthField.placeholder = this.mMonthPlaceHolder; + this.mDayField.placeholder = this.mDayPlaceHolder; + this.mYearField.placeholder = this.mYearPlaceHolder; + + this.mMonthField.setAttribute("min", this.mMinMonth); + this.mMonthField.setAttribute("max", this.mMaxMonth); + this.mMonthField.setAttribute("pginterval", + this.mMonthPageUpDownInterval); + this.mDayField.setAttribute("min", this.mMinDay); + this.mDayField.setAttribute("max", this.mMaxDay); + this.mDayField.setAttribute("pginterval", this.mDayPageUpDownInterval); + this.mYearField.setAttribute("min", this.mMinYear); + this.mYearField.setAttribute("max", this.mMaxYear); + this.mYearField.setAttribute("pginterval", + this.mYearPageUpDownInterval); + + this.mDaySeparator = + document.getAnonymousElementByAttribute(this, "anonid", "sep-first"); + this.mDaySeparator.textContent = this.mSeparatorText; + this.mYearSeparator = + document.getAnonymousElementByAttribute(this, "anonid", "sep-second"); + this.mYearSeparator.textContent = this.mSeparatorText; + + if (this.mInputElement.value) { + this.setFieldsFromInputValue(); + } + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + max) { + return true; + } + + return false; + ]]> + + + + + + this.getDaysInMonth(month, year)) { + // Don't set invalid date, otherwise input element's value will be + // set to empty. + return; + } + + let date = [year, month, day].join("-"); + + this.log("setInputValueFromFields: " + date); + this.mInputElement.setUserInput(date); + ]]> + + + + + + + + + + + + + = targetField.maxLength || n * 10 > max) { + buffer = ""; + this.advanceToNextField(); + } + targetField.setAttribute("typeBuffer", buffer); + } + ]]> + + + + + + + + max) { + value -= (max - min + 1); + } else if (value < min) { + value += (max - min + 1); + } + this.setFieldValue(aTargetField, value); + aTargetField.select(); + ]]> + + + + + + + + + + + + + + + + + + + + + max) { + value = max; + } + } + + if (aField == this.mMonthField || + aField == this.mDayField) { + // prepend zero + if (value < 10) { + value = "0" + value; + } + } else { + // prepend zeroes + if (value < 10) { + value = "000" + value; + } else if (value < 100) { + value = "00" + value; + } else if (value < 1000) { + value = "0" + value; + } + + if (value.toString().length > this.mYearLength && + value.toString().length <= this.mMaxYear.toString().length) { + this.mYearField.size = value.toString().length; + } + } + + aField.value = value; + ]]> + + + + + + + + + + + + @@ -745,6 +1144,12 @@ + + + throw Components.results.NS_ERROR_NOT_IMPLEMENTED; + + + + + + + + + +