Bug 1397114 - Disable smooth scrolling when value changes come from input box draft
authorScott Wu <scottcwwu@gmail.com>
Wed, 20 Sep 2017 16:45:03 +0800
changeset 667587 b3f49918c4efc8d3364639ff1da71b1d352b3b06
parent 666127 ae39864562c6048fdc2950c5dfedb48e247c3300
child 732438 fcd10e5b7ae846267ff9e8d63a9a0a1444825723
push id80770
push userbmo:scwwu@mozilla.com
push dateWed, 20 Sep 2017 10:52:54 +0000
bugs1397114
milestone57.0a1
Bug 1397114 - Disable smooth scrolling when value changes come from input box MozReview-Commit-ID: 9ZLSB2HQvcu
toolkit/content/widgets/datepicker.js
toolkit/content/widgets/spinner.js
--- a/toolkit/content/widgets/datepicker.js
+++ b/toolkit/content/widgets/datepicker.js
@@ -128,32 +128,33 @@ function DatePicker(context) {
           monthYearView: this.context.monthYearView
         })
       };
     },
 
     /**
      * Update date picker and its components.
      */
-    _update() {
+    _update(options = {}) {
       const { dateKeeper, isMonthPickerVisible } = this.state;
 
       if (isMonthPickerVisible) {
         this.state.months = dateKeeper.getMonths();
         this.state.years = dateKeeper.getYears();
       } else {
         this.state.days = dateKeeper.getDays();
       }
 
       this.components.monthYear.setProps({
         isVisible: isMonthPickerVisible,
         dateObj: dateKeeper.state.dateObj,
         months: this.state.months,
         years: this.state.years,
-        toggleMonthPicker: this.state.toggleMonthPicker
+        toggleMonthPicker: this.state.toggleMonthPicker,
+        noSmoothScroll: options.noSmoothScroll
       });
       this.components.calendar.setProps({
         isVisible: !isMonthPickerVisible,
         days: this.state.days,
         weekHeaders: dateKeeper.state.weekHeaders
       });
 
       isMonthPickerVisible ?
@@ -264,17 +265,17 @@ function DatePicker(context) {
       const { dateKeeper } = this.state;
 
       dateKeeper.setCalendarMonth({
         year, month
       });
       dateKeeper.setSelection({
         year, month, day
       });
-      this._update();
+      this._update({ noSmoothScroll: true });
     }
   };
 
   /**
    * MonthYear is a component that handles the month & year spinners
    *
    * @param {Object} options
    *        {
@@ -345,24 +346,24 @@ function DatePicker(context) {
 
       if (props.isVisible) {
         this.context.monthYear.classList.add("active");
         this.components.month.setState({
           value: props.dateObj.getUTCMonth(),
           items: props.months,
           isInfiniteScroll: true,
           isValueSet: this.state.isMonthSet,
-          smoothScroll: !this.state.firstOpened
+          smoothScroll: !(this.state.firstOpened || props.noSmoothScroll)
         });
         this.components.year.setState({
           value: props.dateObj.getUTCFullYear(),
           items: props.years,
           isInfiniteScroll: false,
           isValueSet: this.state.isYearSet,
-          smoothScroll: !this.state.firstOpened
+          smoothScroll: !(this.state.firstOpened || props.noSmoothScroll)
         });
         this.state.firstOpened = false;
       } else {
         this.context.monthYear.classList.remove("active");
         this.state.isMonthSet = false;
         this.state.isYearSet = false;
         this.state.firstOpened = true;
       }
--- a/toolkit/content/widgets/spinner.js
+++ b/toolkit/content/widgets/spinner.js
@@ -119,38 +119,30 @@ function Spinner(props, context) {
       } else {
         this._removeSelection();
       }
     },
 
     /**
      * Whenever scroll event is detected:
      * - Update the index state
-     * - If a smooth scroll has reached its destination, set [isScrolling] state
-     *   to false
      * - If the value has changed, update the [value] state and call [setValue]
      * - If infinite scrolling is on, reset the scrolling position if necessary
      */
     _onScroll() {
       const { items, itemsView, isInfiniteScroll } = this.state;
       const { viewportSize, viewportTopOffset } = this.props;
       const { spinner } = this.elements;
 
       this.state.index = this._getIndexByOffset(spinner.scrollTop);
 
       const value = itemsView[this.state.index + viewportTopOffset].value;
 
-      // Check if smooth scrolling has reached its destination.
-      // This prevents input box jump when input box changes values.
-      if (this.state.value == value && this.state.isScrolling) {
-        this.state.isScrolling = false;
-      }
-
-      // Call setValue if value has changed, and is not smooth scrolling
-      if (this.state.value != value && !this.state.isScrolling) {
+      // Call setValue if value has changed
+      if (this.state.value != value) {
         this.state.value = value;
         this.props.setValue(value);
       }
 
       // Do infinite scroll when items length is bigger or equal to viewport
       // and isInfiniteScroll is not false.
       if (items.length >= viewportSize && isInfiniteScroll) {
         // If the scroll position is near the top or bottom, jump back to the middle
@@ -439,20 +431,16 @@ function Spinner(props, context) {
     /**
      * Smooth scroll to a value based on the index
      *
      * @param  {Number} index: Index number
      */
     _smoothScrollToIndex(index) {
       const element = this.elements.spinner.children[index];
       if (element) {
-        // Set the isScrolling flag before smooth scrolling begins
-        // and remove it when it has reached the destination.
-        // This prevents input box jump when input box changes values
-        this.state.isScrolling = true;
         element.scrollIntoView({
           behavior: "smooth", block: "start"
         });
       }
     },
 
     /**
      * Update the selection state.