Adam Shaw hace 7 años
padre
commit
ed348ff815

+ 1 - 1
demos/locales.html

@@ -98,7 +98,7 @@
     // when the selected option changes, dynamically change the calendar option
     localeSelectorEl.addEventListener('change', function() {
       if (this.value) {
-        calendar.option('locale', this.value);
+        calendar.setOption('locale', this.value);
       }
     });
 

+ 1 - 1
demos/themes.html

@@ -89,7 +89,7 @@
       },
 
       change: function(themeSystem) {
-        calendar.option('themeSystem', themeSystem);
+        calendar.setOption('themeSystem', themeSystem);
       }
 
     });

+ 1 - 1
demos/timezones.html

@@ -72,7 +72,7 @@
 
     // when the timezone selector changes, dynamically change the calendar option
     timezoneSelectorEl.addEventListener('change', function() {
-      calendar.option('timezone', this.value || false);
+      calendar.setOption('timezone', this.value || false);
     });
   });
 

+ 53 - 55
src/Calendar.ts

@@ -159,8 +159,17 @@ export default class Calendar {
     }
 
     this.freezeContentHeight() // do after contentEl is created in renderSkeleton
-    this.renderToolbars(rerenderFlags)
+
     this.renderView(rerenderFlags)
+
+    if (this.view) { // toolbar rendering heavily depends on view
+      this.renderToolbars(rerenderFlags)
+    }
+
+    if (this.updateViewSize()) { // success?
+      this.renderedView.popScroll()
+    }
+
     this.thawContentHeight()
     this.releaseAfterSizingTriggers()
 
@@ -422,46 +431,47 @@ export default class Calendar {
   // -----------------------------------------------------------------------------------------------------------------
 
 
-  // public getter/setter
-  option(name: string | object, value?) {
-    if (typeof name === 'string') {
-      if (value === undefined) { // getter
-        return this.opt(name)
-      } else { // setter for individual option
-        this.setOptions({
-          [name]: value
-        })
-      }
-    } else if (typeof name === 'object' && name) { // compound setter with object input (non-null)
-      this.setOptions(name)
-    }
-  }
+  setOption(name: string, value: any) {
+    this.optionsManager.add(name, value)
+    this.handleOptions(this.optionsManager.computed)
 
+    if (name === 'height' || name === 'contentHeight' || name === 'aspectRatio') {
+      this.updateViewSize(true) // isResize=true
+    } else if (name === 'defaultDate') {
+      // can't change date this way. use gotoDate instead
+    } else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(name)) {
+      // doesn't affect rendering. only interactions.
+    } else {
+      this.batchRendering(() => {
+        let oldView = this.view
 
-  setOptions(optionsHash) {
-    this.optionsManager.add(optionsHash)
-    this.handleOptions(this.optionsManager.computed)
+        // reinstantiate/rerender the entire view
+        if (oldView) {
+          this.viewsByType = {} // so that getViewByType will generate fresh views
+          this.view = this.getViewByType(oldView.type) // will be rendered in renderView
 
-    let optionCnt = 0
-    let optionName
+          // recompute dateProfile
+          this.setCurrentDateMarker(this.state.dateProfile.currentDate)
 
-    for (optionName in optionsHash) {
-      optionCnt++
-    }
+          // transfer scroll from old view
+          let scroll = oldView.queryScroll()
+          scroll.isLocked = true // will prevent view from computing own values
+          this.view.addScroll(scroll)
+        }
 
-    if (optionCnt === 1) {
-      if (optionName === 'height' || optionName === 'contentHeight' || optionName === 'aspectRatio') {
-        this.updateViewSize(true) // force=true
-        return
-      } else if (optionName === 'defaultDate') {
-        return // can't change date this way. use gotoDate instead
-      } else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(optionName)) {
-        return // doesn't affect rendering. only interactions.
-      }
+        this.requestRerender(true) // force=true
+      })
     }
+  }
 
-    this.viewsByType = {}
-    this.requestRerender(true) // force=true
+
+  getOption(name: string) { // getter, used externally
+    return this.optionsManager.computed[name]
+  }
+
+
+  opt(name: string) { // getter, used internally
+    return this.optionsManager.computed[name]
   }
 
 
@@ -482,11 +492,6 @@ export default class Calendar {
   }
 
 
-  opt(optName) {
-    return this.optionsManager.computed[optName]
-  }
-
-
   // Trigger
   // -----------------------------------------------------------------------------------------------------------------
 
@@ -573,10 +578,6 @@ export default class Calendar {
       eventDrag: state.eventDrag,
       eventResize: state.eventResize
     }, forceFlags)
-
-    if (this.updateViewSize()) { // success?
-      renderedView.popScroll()
-    }
   }
 
 
@@ -609,9 +610,7 @@ export default class Calendar {
 
     if (dateOrRange) {
       if ((dateOrRange as DateRangeInput).start && (dateOrRange as DateRangeInput).end) { // a range
-        this.optionsManager.add({ // will not rerender
-          visibleRange: dateOrRange
-        })
+        this.optionsManager.add('visibleRange', dateOrRange) // will not rerender
       } else { // a date
         dateMarker = this.dateEnv.createMarker(dateOrRange as DateInput) // just like gotoDate
       }
@@ -639,10 +638,11 @@ export default class Calendar {
   }
 
 
-  setViewType(viewType: string, dateMarker?: DateMarker) { // internal use only
+  // internal use only
+  // does not cause a render
+  setViewType(viewType: string, dateMarker?: DateMarker) {
     if (!this.view || this.view.type !== viewType) {
-      let view = this.getViewByType(viewType)
-      this.view = view
+      this.view = this.getViewByType(viewType)
 
       // luckily, will always cause a rerender
       this.setCurrentDateMarker(dateMarker || this.state.dateProfile.currentDate)
@@ -731,8 +731,6 @@ export default class Calendar {
 
 
   setDateProfile(dateProfile: DateProfile) {
-    this.view.updateMiscDateProps(dateProfile) // for legacy!
-
     this.dispatch({
       type: 'SET_DATE_PROFILE',
       dateProfile: dateProfile
@@ -784,13 +782,13 @@ export default class Calendar {
   }
 
 
-  updateViewSize(force: boolean = false) {
+  updateViewSize(isResize: boolean = false) {
     let { renderedView } = this
     let scroll
 
     if (!this.ignoreUpdateViewSize && renderedView) {
 
-      if (force) {
+      if (isResize) {
         this.calcSize()
         scroll = renderedView.queryScroll()
       }
@@ -800,12 +798,12 @@ export default class Calendar {
       renderedView.updateSize(
         this.getSuggestedViewHeight(),
         this.isHeightAuto(),
-        force
+        isResize
       )
 
       this.ignoreUpdateViewSize--
 
-      if (force) {
+      if (isResize) {
         renderedView.applyScroll(scroll)
       }
 

+ 2 - 2
src/OptionsManager.ts

@@ -20,8 +20,8 @@ export default class OptionsManager {
   }
 
 
-  add(newOptionHash) {
-    assignTo(this.dynamicOverrides, newOptionHash)
+  add(name, value) {
+    this.dynamicOverrides[name] = value
     this.compute()
   }
 

+ 17 - 5
src/View.ts

@@ -30,7 +30,7 @@ export default abstract class View extends DateComponent {
   viewSpec: any
   options: any // hash containing all options. already merged with view-specific-options
 
-  queuedScroll: object
+  queuedScroll: any
 
   eventOrderSpecs: any // criteria for ordering events when they have same date/time
 
@@ -183,6 +183,7 @@ export default abstract class View extends DateComponent {
 
   // if dateProfile not specified, uses current
   renderDates() {
+    this.updateMiscDateProps(this.dateProfile)
     super.renderDates()
     this.addScroll({ isDateInit: true })
     this.startNowIndicator() // shouldn't render yet because updateSize will be called soon
@@ -317,7 +318,9 @@ export default abstract class View extends DateComponent {
   addScroll(scroll) {
     let queuedScroll = this.queuedScroll || (this.queuedScroll = {})
 
-    assignTo(queuedScroll, scroll)
+    if (!queuedScroll.isLocked) {
+      assignTo(queuedScroll, scroll)
+    }
   }
 
 
@@ -333,7 +336,7 @@ export default abstract class View extends DateComponent {
 
 
   queryScroll() {
-    let scroll = {}
+    let scroll = {} as any
 
     if (this.renderedFlags.dates) {
       assignTo(scroll, this.queryDateScroll())
@@ -344,8 +347,17 @@ export default abstract class View extends DateComponent {
 
 
   applyScroll(scroll) {
-    if (scroll.isDateInit && this.renderedFlags.dates) {
-      assignTo(scroll, this.computeInitialDateScroll())
+
+    if (scroll.isLocked) {
+      delete scroll.isLocked
+    }
+
+    if (scroll.isDateInit) {
+      delete scroll.isDateInit
+
+      if (this.renderedFlags.dates) {
+        assignTo(scroll, this.computeInitialDateScroll())
+      }
     }
 
     if (this.renderedFlags.dates) {

+ 1 - 1
tests/automated/event-data/dynamic-options.js

@@ -14,7 +14,7 @@ describe('setting option dynamically', function() {
 
     expect(fetchCnt).toBe(1)
 
-    currentCalendar.option('selectable', true)
+    currentCalendar.setOption('selectable', true)
 
     setTimeout(function() { // in case async
       expect(fetchCnt).toBe(1)

+ 2 - 2
tests/automated/legacy/businessHours.js

@@ -58,7 +58,7 @@ describe('businessHours', function() {
         })
 
         expect(queryNonBusinessSegs().length).toBe(0)
-        currentCalendar.option('businessHours', true)
+        currentCalendar.setOption('businessHours', true)
         expect(queryNonBusinessSegs().length).toBeGreaterThan(0)
       })
 
@@ -69,7 +69,7 @@ describe('businessHours', function() {
         })
 
         expect(queryNonBusinessSegs().length).toBeGreaterThan(0)
-        currentCalendar.option('businessHours', false)
+        currentCalendar.setOption('businessHours', false)
         expect(queryNonBusinessSegs().length).toBe(0)
       })
     })

+ 1 - 1
tests/automated/legacy/events-function.js

@@ -65,7 +65,7 @@ describe('events as a function', function() {
           expect(arg.start).toEqualDate('2014-04-27')
           expect(arg.end).toEqualDate('2014-06-08')
           setTimeout(function() {
-            currentCalendar.option('timezone', 'UTC')
+            currentCalendar.setOption('timezone', 'UTC')
           }, 0)
         } else if (callCnt === 2) {
           expect(arg.timeZone).toEqual('UTC')

+ 1 - 1
tests/automated/legacy/footer-rendering.js

@@ -37,7 +37,7 @@ describe('footer rendering', function() {
       }
     })
     expect($('.fc-footer-toolbar')).toBeInDOM()
-    currentCalendar.option('footer', false)
+    currentCalendar.setOption('footer', false)
     expect($('.fc-footer-toolbar')).not.toBeInDOM()
   })
 

+ 1 - 1
tests/automated/legacy/header-rendering.js

@@ -64,7 +64,7 @@ describe('header rendering', function() {
   it('allow for dynamically changing', function() {
     initCalendar()
     expect($('.fc-toolbar')).toBeInDOM()
-    currentCalendar.option('header', false)
+    currentCalendar.setOption('header', false)
     expect($('.fc-toolbar')).not.toBeInDOM()
   })
 

+ 2 - 21
tests/automated/legacy/height-and-contentHeight.js

@@ -32,16 +32,10 @@
 
       // relies on asAMethod (boolean)
       // otherOptions: other calendar options to dynamically set (assumes asAMethod)
-      function init(heightVal, otherOptions) {
+      function init(heightVal) {
         if (asAMethod) {
           initCalendar({}, calendarEl)
-
-          if (otherOptions === undefined) {
-            currentCalendar.option(heightProp, heightVal)
-          } else {
-            otherOptions[heightProp] = heightVal // reuse same object. insert height option
-            currentCalendar.option(otherOptions)
-          }
+          currentCalendar.setOption(heightProp, heightVal)
         } else {
           initCalendar({ [heightProp]: heightVal }, calendarEl)
         }
@@ -139,19 +133,6 @@
                       expect($('.fc-day-grid-container')).toHaveScrollbars()
                     })
                   })
-
-                  describe('when setting height, contentHeight option with other options', function() {
-                    pushOptions({
-                      [heightProp]: 600 // initialize with another height
-                    })
-                    beforeEach(function() {
-                      init(250, { minTime: '00:00' }) // then change height, providing other opts to set too
-                    })
-
-                    it('height of the view container should change', function() {
-                      expectHeight(250)
-                    })
-                  })
                 })
               })
 

+ 2 - 2
tests/automated/legacy/isRTL.js

@@ -4,7 +4,7 @@ describe('isRTL', function() {
     initCalendar({
       locale: 'ar' // Arabic is RTL
     })
-    expect(currentCalendar.option('isRTL')).toEqual(true)
+    expect(currentCalendar.getOption('isRTL')).toEqual(true)
   })
 
   // NOTE: don't put tests related to other options in here!
@@ -19,7 +19,7 @@ describe('isRTL', function() {
     expect($el).toHaveClass('fc-ltr')
     expect($el).not.toHaveClass('fc-rtl')
 
-    currentCalendar.option('isRTL', true)
+    currentCalendar.setOption('isRTL', true)
 
     expect($el).toHaveClass('fc-rtl')
     expect($el).not.toHaveClass('fc-ltr')

+ 2 - 2
tests/automated/legacy/locale.js

@@ -25,10 +25,10 @@ describe('locale', function() {
     expect($('h2', calendarEl)).toHaveText('julio de 2016')
     expect($(calendarEl)).not.toHaveClass('fc-rtl')
 
-    currentCalendar.option('locale', 'fr')
+    currentCalendar.setOption('locale', 'fr')
     expect($('h2', calendarEl)).toHaveText('juillet 2016')
 
-    currentCalendar.option('locale', 'ar') // NOTE: we had problems testing for RTL title text
+    currentCalendar.setOption('locale', 'ar') // NOTE: we had problems testing for RTL title text
     expect($(calendarEl)).toHaveClass('fc-rtl')
   })
 

+ 4 - 4
tests/automated/legacy/theme.js

@@ -17,7 +17,7 @@ describe('theme', function() {
     var scrollTop = $('.fc-scroller').scrollTop()
 
     // change option!
-    currentCalendar.option('theme', true)
+    currentCalendar.setOption('theme', true)
 
     expect($('.fc')).toHaveClass('ui-widget')
     expect($('.fc')).not.toHaveClass('fc-unthemed')
@@ -40,9 +40,9 @@ describe('theme', function() {
     expect($('.fc-nonbusiness').length).toBe(0)
 
     // change option!
-    currentCalendar.option({
-      theme: true,
-      businessHours: true
+    currentCalendar.batchRendering(function() {
+      currentCalendar.setOption('theme', true)
+      currentCalendar.setOption('businessHours', true)
     })
 
     expect($('.fc')).toHaveClass('ui-widget')

+ 1 - 1
tests/automated/legacy/timezone.js

@@ -104,7 +104,7 @@ describe('timezone', function() {
         callCnt++
         if (callCnt === 1) {
           expectLocalTimezone()
-          currentCalendar.option('timezone', 'UTC') // will cause second call...
+          currentCalendar.setOption('timezone', 'UTC') // will cause second call...
         } else if (callCnt === 2) {
           expectUtcTimezone()
           done()

+ 3 - 3
tests/automated/theme/switching.js

@@ -4,21 +4,21 @@ describe('theme switching', function() {
   it('can switch from standard to jquery-ui', function() {
     initCalendar()
     verifyStandardTheme()
-    currentCalendar.option('themeSystem', 'jquery-ui')
+    currentCalendar.setOption('themeSystem', 'jquery-ui')
     verifyJqueryUiTheme()
   })
 
   it('can switch from jquery-ui to boostrap3', function() {
     initCalendar({ themeSystem: 'jquery-ui' })
     verifyJqueryUiTheme()
-    currentCalendar.option('themeSystem', 'bootstrap3')
+    currentCalendar.setOption('themeSystem', 'bootstrap3')
     verifyBootstrapTheme()
   })
 
   it('can switch from jquery-ui to boostrap4', function() {
     initCalendar({ themeSystem: 'jquery-ui' })
     verifyJqueryUiTheme()
-    currentCalendar.option('themeSystem', 'bootstrap4')
+    currentCalendar.setOption('themeSystem', 'bootstrap4')
     verifyBootstrap4Theme()
   })
 

+ 1 - 1
tests/automated/view-dates/visibleRange.js

@@ -70,7 +70,7 @@ describe('visibleRange', function() {
         initCalendar({
           defaultView: 'basic'
         })
-        currentCalendar.option('visibleRange', {
+        currentCalendar.setOption('visibleRange', {
           start: startInput,
           end: endInput
         })