Adam Shaw 7 éve
szülő
commit
8d037f422d

+ 48 - 16
src/Calendar.ts

@@ -74,7 +74,7 @@ export default class Calendar {
   // isDisplaying: boolean = false // installed in DOM? accepting renders?
   // isDisplaying: boolean = false // installed in DOM? accepting renders?
   needsRerender: boolean = false // needs a render?
   needsRerender: boolean = false // needs a render?
   needsFullRerender: boolean = false
   needsFullRerender: boolean = false
-  isRendering: boolean = false // currently in the renderComponent function?
+  isRendering: boolean = false // currently in the executeRender function?
   renderingPauseDepth: number = 0
   renderingPauseDepth: number = 0
   renderableEventStore: EventStore
   renderableEventStore: EventStore
   buildDelayedRerender: any
   buildDelayedRerender: any
@@ -108,8 +108,15 @@ export default class Calendar {
   }
   }
 
 
 
 
+  // public API
+  get view(): View {
+    return this.component ? this.component.view : null
+  }
+
+
+  // public API :(
   getView(): View {
   getView(): View {
-    return this.component.view
+    return this.view // calls getter
   }
   }
 
 
 
 
@@ -121,7 +128,7 @@ export default class Calendar {
     if (!this.component) {
     if (!this.component) {
       this.renderableEventStore = createEmptyEventStore()
       this.renderableEventStore = createEmptyEventStore()
       this.bindHandlers()
       this.bindHandlers()
-      this.renderComponent()
+      this.executeRender()
     } else {
     } else {
       this.requestRerender(true)
       this.requestRerender(true)
     }
     }
@@ -131,7 +138,7 @@ export default class Calendar {
   destroy() {
   destroy() {
     if (this.component) {
     if (this.component) {
       this.unbindHandlers()
       this.unbindHandlers()
-      this.component.destroy()
+      this.component.destroy() // don't null-out. in case API needs access
       this.component = null
       this.component = null
     }
     }
   }
   }
@@ -293,8 +300,7 @@ export default class Calendar {
       !this.renderingPauseDepth && // not paused
       !this.renderingPauseDepth && // not paused
       !this.isRendering // not currently in the render loop
       !this.isRendering // not currently in the render loop
     ) {
     ) {
-      this.renderComponent(this.needsFullRerender)
-      this.needsFullRerender = false
+      this.executeRender()
     }
     }
   }
   }
 
 
@@ -310,7 +316,27 @@ export default class Calendar {
   // Rendering
   // Rendering
   // -----------------------------------------------------------------------------------------------------------------
   // -----------------------------------------------------------------------------------------------------------------
 
 
-  renderComponent(needsFull = false) {
+  executeRender() {
+    let { needsFullRerender } = this // save before clearing
+
+    // clear these BEFORE the render so that new values will accumulate during render
+    this.needsRerender = false
+    this.needsFullRerender = false
+
+    this.isRendering = true
+    this.renderComponent(needsFullRerender)
+    this.isRendering = false
+
+    // received a rerender request while rendering
+    if (this.needsRerender) {
+      this.delayedRerender()
+    }
+  }
+
+  /*
+  don't call this directly. use executeRender instead
+  */
+  renderComponent(needsFull) {
     let { state, component } = this
     let { state, component } = this
     let { viewType } = state
     let { viewType } = state
     let viewSpec = this.viewSpecs[viewType]
     let viewSpec = this.viewSpecs[viewType]
@@ -333,8 +359,6 @@ export default class Calendar {
       viewSpec.options
       viewSpec.options
     )
     )
 
 
-    this.isRendering = true
-
     if (needsFull || !component) {
     if (needsFull || !component) {
 
 
       if (component) {
       if (component) {
@@ -367,7 +391,6 @@ export default class Calendar {
     }
     }
 
 
     this.releaseAfterSizingTriggers()
     this.releaseAfterSizingTriggers()
-    this.isRendering = false
   }
   }
 
 
 
 
@@ -393,7 +416,16 @@ export default class Calendar {
     } else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(name)) {
     } else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(name)) {
       // doesn't affect rendering. only interactions.
       // doesn't affect rendering. only interactions.
     } else {
     } else {
-      this.renderComponent(true)
+
+      /* HACK
+      has the same effect as calling this.requestRerender(true)
+      but recomputes the state's dateProfile
+      */
+      this.needsFullRerender = true
+      this.dispatch({
+        type: 'SET_VIEW_TYPE',
+        viewType: this.state.viewType
+      })
     }
     }
   }
   }
 
 
@@ -414,7 +446,7 @@ export default class Calendar {
 
 
 
 
   viewOpts() {
   viewOpts() {
-    return this.viewSpecs[this.state.viewType]
+    return this.viewSpecs[this.state.viewType].options
   }
   }
 
 
 
 
@@ -442,7 +474,7 @@ export default class Calendar {
 
 
     // ineffecient to do every time?
     // ineffecient to do every time?
     this.dateProfileGenerators = mapHash(this.viewSpecs, (viewSpec) => {
     this.dateProfileGenerators = mapHash(this.viewSpecs, (viewSpec) => {
-      return new viewSpec.class.dateProfileGeneratorClass(viewSpec, this)
+      return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, this)
     })
     })
   }
   }
 
 
@@ -697,7 +729,7 @@ export default class Calendar {
   windowResize(ev: Event) {
   windowResize(ev: Event) {
     if ((ev as any).target === window) { // not a jqui resize event
     if ((ev as any).target === window) { // not a jqui resize event
       if (this.resizeComponent()) { // returns true on success
       if (this.resizeComponent()) { // returns true on success
-        this.publiclyTrigger('windowResize', [ this.component.view ])
+        this.publiclyTrigger('windowResize', [ this.view ])
       }
       }
     }
     }
   }
   }
@@ -774,7 +806,7 @@ export default class Calendar {
     let arg = buildDateSpanApi(selection, this.dateEnv)
     let arg = buildDateSpanApi(selection, this.dateEnv)
 
 
     arg.jsEvent = pev ? pev.origEvent : null
     arg.jsEvent = pev ? pev.origEvent : null
-    arg.view = this.component.view
+    arg.view = this.view
 
 
     this.publiclyTrigger('select', [ arg ])
     this.publiclyTrigger('select', [ arg ])
 
 
@@ -788,7 +820,7 @@ export default class Calendar {
     this.publiclyTrigger('unselect', [
     this.publiclyTrigger('unselect', [
       {
       {
         jsEvent: pev ? pev.origEvent : null,
         jsEvent: pev ? pev.origEvent : null,
-        view: this.component.view
+        view: this.view
       }
       }
     ])
     ])
   }
   }

+ 1 - 0
src/CalendarComponent.ts

@@ -215,6 +215,7 @@ export default class CalendarComponent extends Component<CalendarComponentProps>
     super.updateSize(totalHeight, isAuto, isResize)
     super.updateSize(totalHeight, isAuto, isResize)
 
 
     this.view.updateSize(this.viewHeight, this.isHeightAuto, isResize)
     this.view.updateSize(this.viewHeight, this.isHeightAuto, isResize)
+    this.view.updateNowIndicator() // we need to guarantee this will run after updateSize
   }
   }
 
 
   computeHeightVars() {
   computeHeightVars() {

+ 1 - 1
src/DateProfileGenerator.ts

@@ -208,7 +208,7 @@ export default class DateProfileGenerator {
     let start = range.start
     let start = range.start
     let end = range.end
     let end = range.end
 
 
-    if ((this.viewSpec.class as any).usesMinMaxTime) {
+    if ((this.viewSpec.class as any).prototype.usesMinMaxTime) {
 
 
       // expand active range if minTime is negative (why not when positive?)
       // expand active range if minTime is negative (why not when positive?)
       if (asRoughDays(minTime) < 0) {
       if (asRoughDays(minTime) < 0) {

+ 5 - 17
src/View.ts

@@ -15,10 +15,9 @@ import { ComponentContext } from './component/Component'
 
 
 export default abstract class View extends DateComponent {
 export default abstract class View extends DateComponent {
 
 
-  // whether minTime/maxTime will affect the activeRange. Views must opt-in.
-  // initialized after class
-  static usesMinMaxTime: boolean = false
-  static dateProfileGeneratorClass: any // initialized after class. used by Calendar
+  // config properties, initialized after class on prototype
+  usesMinMaxTime: boolean // whether minTime/maxTime will affect the activeRange. Views must opt-in.
+  dateProfileGeneratorClass: any // initialized after class. used by Calendar
 
 
   on: EmitterInterface['on']
   on: EmitterInterface['on']
   one: EmitterInterface['one']
   one: EmitterInterface['one']
@@ -245,17 +244,6 @@ export default abstract class View extends DateComponent {
   }
   }
 
 
 
 
-  /* Dimensions
-  ------------------------------------------------------------------------------------------------------------------*/
-
-
-  updateSize(totalHeight: number, isAuto: boolean, isResize: boolean) {
-    super.updateSize(totalHeight, isAuto, isResize)
-
-    this.updateNowIndicator()
-  }
-
-
   /* Scroller
   /* Scroller
   ------------------------------------------------------------------------------------------------------------------*/
   ------------------------------------------------------------------------------------------------------------------*/
 
 
@@ -333,5 +321,5 @@ export default abstract class View extends DateComponent {
 
 
 EmitterMixin.mixInto(View)
 EmitterMixin.mixInto(View)
 
 
-View.usesMinMaxTime = false
-View.dateProfileGeneratorClass = DateProfileGenerator
+View.prototype.usesMinMaxTime = false
+View.prototype.dateProfileGeneratorClass = DateProfileGenerator

+ 1 - 1
src/agenda/AgendaView.ts

@@ -467,4 +467,4 @@ function buildInteractionForDayGrid(state: EventInteractionUiState): EventIntera
   return null
   return null
 }
 }
 
 
-AgendaView.usesMinMaxTime = true // indicates that minTime/maxTime affects rendering
+AgendaView.prototype.usesMinMaxTime = true // indicates that minTime/maxTime affects rendering

+ 4 - 2
src/basic/BasicView.ts

@@ -32,7 +32,7 @@ export default class BasicView extends View {
 
 
   scroller: ScrollComponent
   scroller: ScrollComponent
   dayGrid: DayGrid // the main subcomponent that does most of the heavy lifting
   dayGrid: DayGrid // the main subcomponent that does most of the heavy lifting
-  colWeekNumbersVisible: boolean = false
+  colWeekNumbersVisible: boolean
 
 
   weekNumberWidth: any // width of all the week-number cells running down the side
   weekNumberWidth: any // width of all the week-number cells running down the side
 
 
@@ -67,6 +67,8 @@ export default class BasicView extends View {
         this.dayGrid.cellWeekNumbersVisible = false
         this.dayGrid.cellWeekNumbersVisible = false
         this.colWeekNumbersVisible = true
         this.colWeekNumbersVisible = true
       }
       }
+    } else {
+      this.colWeekNumbersVisible = false
     }
     }
   }
   }
 
 
@@ -271,7 +273,7 @@ export default class BasicView extends View {
 }
 }
 
 
 
 
-BasicView.dateProfileGeneratorClass = BasicViewDateProfileGenerator
+BasicView.prototype.dateProfileGeneratorClass = BasicViewDateProfileGenerator
 BasicView.prototype.dayGridClass = DayGrid
 BasicView.prototype.dayGridClass = DayGrid
 
 
 
 

+ 1 - 1
src/basic/MonthView.ts

@@ -29,4 +29,4 @@ export default class MonthView extends BasicView {
 
 
 }
 }
 
 
-MonthView.dateProfileGeneratorClass = MonthViewDateProfileGenerator
+MonthView.prototype.dateProfileGeneratorClass = MonthViewDateProfileGenerator

+ 15 - 5
src/component/DateComponent.ts

@@ -107,7 +107,7 @@ export default class DateComponent extends Component<DateComponentProps> {
     this.subrender('afterSkeletonRender', [], 'beforeSkeletonUnrender', true)
     this.subrender('afterSkeletonRender', [], 'beforeSkeletonUnrender', true)
     let dateId = this.subrender('_renderDates', [ props.dateProfile ], '_unrenderDates', true)
     let dateId = this.subrender('_renderDates', [ props.dateProfile ], '_unrenderDates', true)
     this.subrender('renderBusinessHours', [ props.businessHours, dateId ], 'unrenderBusinessHours', true)
     this.subrender('renderBusinessHours', [ props.businessHours, dateId ], 'unrenderBusinessHours', true)
-    this.subrender('renderDateSelection', [ props.dateSelection, dateId ], 'unrenderDateSelection', true)
+    this.subrender('renderDateSelectionState', [ props.dateSelection, dateId ], 'unrenderDateSelectionState', true)
     let evId = this.subrender('renderEvents', [ props.eventStore, props.eventUis, dateId ], 'unrenderEvents', true)
     let evId = this.subrender('renderEvents', [ props.eventStore, props.eventUis, dateId ], 'unrenderEvents', true)
     this.subrender('selectEventsByInstanceId', [ props.eventSelection, evId ], 'unselectAllEvents', true)
     this.subrender('selectEventsByInstanceId', [ props.eventSelection, evId ], 'unselectAllEvents', true)
     this.subrender('renderEventDragState', [ props.eventDrag, dateId ], 'unrenderEventDragState', true)
     this.subrender('renderEventDragState', [ props.eventDrag, dateId ], 'unrenderEventDragState', true)
@@ -128,7 +128,7 @@ export default class DateComponent extends Component<DateComponentProps> {
       this.computeBusinessHoursSize()
       this.computeBusinessHoursSize()
     }
     }
 
 
-    if (isResize || map.has('renderDateSelection') || map.has('renderEventDragState') || map.has('renderEventResizeState')) {
+    if (isResize || map.has('renderDateSelectionState') || map.has('renderEventDragState') || map.has('renderEventResizeState')) {
       this.computeHighlightSize()
       this.computeHighlightSize()
       this.computeMirrorSize()
       this.computeMirrorSize()
     }
     }
@@ -141,7 +141,7 @@ export default class DateComponent extends Component<DateComponentProps> {
       this.assignBusinessHoursSize()
       this.assignBusinessHoursSize()
     }
     }
 
 
-    if (isResize || map.has('renderDateSelection') || map.has('renderEventDragState') || map.has('renderEventResizeState')) {
+    if (isResize || map.has('renderDateSelectionState') || map.has('renderEventDragState') || map.has('renderEventResizeState')) {
       this.assignHighlightSize()
       this.assignHighlightSize()
       this.assignMirrorSize()
       this.assignMirrorSize()
     }
     }
@@ -251,12 +251,22 @@ export default class DateComponent extends Component<DateComponentProps> {
   // Date Selection
   // Date Selection
   // ---------------------------------------------------------------------------------------------------------------
   // ---------------------------------------------------------------------------------------------------------------
 
 
-  renderDateSelection(selection: DateSpan) {
+  renderDateSelectionState(selection: DateSpan) {
+    if (selection) {
+      this.renderDateSelection(selection)
+    }
+  }
+
+  unrenderDateSelectionState(selection: DateSpan) {
     if (selection) {
     if (selection) {
-      this.renderHighlightSegs(this.selectionToSegs(selection, false))
+      this.unrenderDateSelection()
     }
     }
   }
   }
 
 
+  renderDateSelection(selection: DateSpan) {
+    this.renderHighlightSegs(this.selectionToSegs(selection, false))
+  }
+
   unrenderDateSelection() {
   unrenderDateSelection() {
     this.unrenderHighlight()
     this.unrenderHighlight()
   }
   }

+ 13 - 9
src/reducers/eventSources.ts

@@ -18,7 +18,11 @@ export default function(eventSources: EventSourceHash, action: Action, dateProfi
     case 'SET_VIEW_TYPE':
     case 'SET_VIEW_TYPE':
     case 'SET_DATE':
     case 'SET_DATE':
     case 'SET_DATE_PROFILE':
     case 'SET_DATE_PROFILE':
-      return fetchDirtySources(eventSources, dateProfile.activeRange, calendar)
+      if (dateProfile) {
+        return fetchDirtySources(eventSources, dateProfile.activeRange, calendar)
+      } else {
+        return eventSources
+      }
 
 
     case 'FETCH_EVENT_SOURCES':
     case 'FETCH_EVENT_SOURCES':
     case 'CHANGE_TIMEZONE':
     case 'CHANGE_TIMEZONE':
@@ -54,7 +58,9 @@ function addSources(eventSourceHash: EventSourceHash, sources: EventSource[], fe
     hash[source.sourceId] = source
     hash[source.sourceId] = source
   }
   }
 
 
-  hash = fetchDirtySources(hash, fetchRange, calendar)
+  if (fetchRange) {
+    hash = fetchDirtySources(hash, fetchRange, calendar)
+  }
 
 
   return assignTo({}, eventSourceHash, hash)
   return assignTo({}, eventSourceHash, hash)
 }
 }
@@ -67,7 +73,7 @@ function removeSource(eventSourceHash: EventSourceHash, sourceId: string): Event
 }
 }
 
 
 
 
-function fetchDirtySources(sourceHash: EventSourceHash, fetchRange: DateRange | null, calendar: Calendar): EventSourceHash {
+function fetchDirtySources(sourceHash: EventSourceHash, fetchRange: DateRange, calendar: Calendar): EventSourceHash {
   return fetchSourcesByIds(
   return fetchSourcesByIds(
     sourceHash,
     sourceHash,
     filterHash(sourceHash, function(eventSource) {
     filterHash(sourceHash, function(eventSource) {
@@ -79,25 +85,23 @@ function fetchDirtySources(sourceHash: EventSourceHash, fetchRange: DateRange |
 }
 }
 
 
 
 
-function isSourceDirty(eventSource: EventSource, fetchRange: DateRange | null, calendar: Calendar) {
+function isSourceDirty(eventSource: EventSource, fetchRange: DateRange, calendar: Calendar) {
 
 
   if (!doesSourceNeedRange(eventSource)) {
   if (!doesSourceNeedRange(eventSource)) {
     return !eventSource.latestFetchId
     return !eventSource.latestFetchId
-  } else if (fetchRange) {
+  } else {
     return !calendar.opt('lazyFetching') ||
     return !calendar.opt('lazyFetching') ||
       !eventSource.fetchRange ||
       !eventSource.fetchRange ||
       fetchRange.start < eventSource.fetchRange.start ||
       fetchRange.start < eventSource.fetchRange.start ||
       fetchRange.end > eventSource.fetchRange.end
       fetchRange.end > eventSource.fetchRange.end
   }
   }
-
-  return false
 }
 }
 
 
 
 
 function fetchSourcesByIds(
 function fetchSourcesByIds(
   prevSources: EventSourceHash,
   prevSources: EventSourceHash,
   sourceIdHash: { [sourceId: string]: any },
   sourceIdHash: { [sourceId: string]: any },
-  fetchRange: DateRange | null,
+  fetchRange: DateRange,
   calendar: Calendar
   calendar: Calendar
 ): EventSourceHash {
 ): EventSourceHash {
   let nextSources: EventSourceHash = {}
   let nextSources: EventSourceHash = {}
@@ -116,7 +120,7 @@ function fetchSourcesByIds(
 }
 }
 
 
 
 
-function fetchSource(eventSource: EventSource, fetchRange: DateRange | null, calendar: Calendar) {
+function fetchSource(eventSource: EventSource, fetchRange: DateRange, calendar: Calendar) {
   let sourceDef = getEventSourceDef(eventSource.sourceDefId)
   let sourceDef = getEventSourceDef(eventSource.sourceDefId)
   let fetchId = String(uid++)
   let fetchId = String(uid++)