Bug 1337319 - Order month and year spinners based on locale datetime format r=mconley
authorScott Wu <scottcwwu@gmail.com>
Thu, 16 Feb 2017 15:57:54 +0800
changeset 373264 8b02cdbaa32e9a4deedb9cb7fe8eb8a5268c27c6
parent 373263 a29f11fae37711a4d09557377286a8688e652334
child 373265 1d16150ba521dc1e7d5a71b8bb01beef61c47447
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1337319
milestone54.0a1
Bug 1337319 - Order month and year spinners based on locale datetime format r=mconley MozReview-Commit-ID: AmAVjybJZ6A
toolkit/content/widgets/datepicker.js
toolkit/content/widgets/spinner.js
toolkit/themes/shared/datetimeinputpickers.css
--- a/toolkit/content/widgets/datepicker.js
+++ b/toolkit/content/widgets/datepicker.js
@@ -57,16 +57,18 @@ function DatePicker(context) {
 
       this.state = {
         dateKeeper,
         locale,
         isMonthPickerVisible: false,
         isYearSet: false,
         isMonthSet: false,
         isDateSet: false,
+        datetimeOrders: new Intl.DateTimeFormat(locale)
+                          .formatToParts(new Date(0)).map(part => part.type),
         getDayString: new Intl.NumberFormat(locale).format,
         getWeekHeaderString: weekday => weekdayStrings[weekday],
         getMonthString: month => monthStrings[month],
         setValue: ({ dateValue, selectionValue }) => {
           dateKeeper.setValue(dateValue);
           this.state.selectionValue = selectionValue;
           this.state.isYearSet = true;
           this.state.isMonthSet = true;
@@ -105,16 +107,17 @@ function DatePicker(context) {
         }, {
           weekHeader: this.context.weekHeader,
           daysView: this.context.daysView
         }),
         monthYear: new MonthYear({
           setYear: this.state.setYear,
           setMonth: this.state.setMonth,
           getMonthString: this.state.getMonthString,
+          datetimeOrders: this.state.datetimeOrders,
           locale: this.state.locale
         }, {
           monthYear: this.context.monthYear,
           monthYearView: this.context.monthYearView
         })
       };
     },
 
@@ -282,37 +285,45 @@ function DatePicker(context) {
    * MonthYear is a component that handles the month & year spinners
    *
    * @param {Object} options
    *        {
    *          {String} locale
    *          {Function} setYear
    *          {Function} setMonth
    *          {Function} getMonthString
+   *          {Array<String>} datetimeOrders
    *        }
    * @param {DOMElement} context
    */
   function MonthYear(options, context) {
     const spinnerSize = 5;
     const yearFormat = new Intl.DateTimeFormat(options.locale, { year: "numeric" }).format;
     const dateFormat = new Intl.DateTimeFormat(options.locale, { year: "numeric", month: "long" }).format;
+    const spinnerOrder =
+      options.datetimeOrders.indexOf("month") < options.datetimeOrders.indexOf("year") ?
+      "order-month-year" : "order-year-month";
+
+    context.monthYearView.classList.add(spinnerOrder);
 
     this.context = context;
     this.state = { dateFormat };
     this.props = {};
     this.components = {
       month: new Spinner({
+        id: "spinner-month",
         setValue: month => {
           this.state.isMonthSet = true;
           options.setMonth(month);
         },
         getDisplayString: options.getMonthString,
         viewportSize: spinnerSize
       }, context.monthYearView),
       year: new Spinner({
+        id: "spinner-year",
         setValue: year => {
           this.state.isYearSet = true;
           options.setYear(year);
         },
         getDisplayString: year => yearFormat(new Date(new Date(0).setFullYear(year))),
         viewportSize: spinnerSize
       }, context.monthYearView)
     };
--- a/toolkit/content/widgets/spinner.js
+++ b/toolkit/content/widgets/spinner.js
@@ -37,17 +37,17 @@ function Spinner(props, context) {
      *             as localized strings.
      *           {Number} viewportSize [optional]: Number of items in a
      *             viewport.
      *           {Boolean} hideButtons [optional]: Hide up & down buttons
      *           {Number} rootFontSize [optional]: Used to support zoom in/out
      *         }
      */
     _init(props) {
-      const { setValue, getDisplayString, hideButtons, rootFontSize = 10 } = props;
+      const { id, setValue, getDisplayString, hideButtons, rootFontSize = 10 } = props;
 
       const spinnerTemplate = document.getElementById("spinner-template");
       const spinnerElement = document.importNode(spinnerTemplate.content, true);
 
       // Make sure viewportSize is an odd number because we want to have the selected
       // item in the center. If it's an even number, use the default size instead.
       const viewportSize = props.viewportSize % 2 ? props.viewportSize : VIEWPORT_SIZE;
 
@@ -67,16 +67,19 @@ function Spinner(props, context) {
         spinner: spinnerElement.querySelector(".spinner"),
         up: spinnerElement.querySelector(".up"),
         down: spinnerElement.querySelector(".down"),
         itemsViewElements: []
       };
 
       this.elements.spinner.style.height = (ITEM_HEIGHT * viewportSize) + "rem";
 
+      if (id) {
+        this.elements.container.id = id;
+      }
       if (hideButtons) {
         this.elements.container.classList.add("hide-buttons");
       }
 
       this.context.appendChild(spinnerElement);
       this._attachEventListeners();
     },
 
--- a/toolkit/themes/shared/datetimeinputpickers.css
+++ b/toolkit/themes/shared/datetimeinputpickers.css
@@ -166,16 +166,26 @@ button.month-year.active::after {
   transition: transform 0.15s;
 }
 
 .month-year-view.hidden .spinner > div {
   transform: scaleY(2.5);
   transition: none;
 }
 
+.order-month-year > #spinner-month,
+.order-year-month > #spinner-year {
+  order: 1;
+}
+
+.order-month-year > #spinner-year,
+.order-year-month > #spinner-month {
+  order: 2;
+}
+
 .calendar-container {
   cursor: default;
   display: flex;
   flex-direction: column;
   width: var(--calendar-width);
 }
 
 .week-header {