Adam Shaw 7 лет назад
Родитель
Сommit
a767f126ea

+ 1 - 1
src/Calendar.ts

@@ -445,7 +445,7 @@ export default class Calendar {
 
     // ineffecient to do every time?
     this.dateProfileGenerators = mapHash(this.viewSpecs, (viewSpec) => {
-      return new DateProfileGenerator(viewSpec, this)
+      return new viewSpec.class.dateProfileGeneratorClass(viewSpec, this)
     })
   }
 

+ 2 - 0
src/CalendarComponent.ts

@@ -197,6 +197,8 @@ export default class CalendarComponent extends Component<CalendarComponentProps>
   // -----------------------------------------------------------------------------------------------------------------
 
   updateSize(isResize = false) {
+    super.updateSize(isResize)
+
     if (isResize) {
       this.clearHeightVars()
     }

+ 1 - 1
src/Toolbar.ts

@@ -272,7 +272,7 @@ export default class Toolbar extends Component<ToolbarRenderProps> {
     let className = this.theme.getClass('stateActive')
 
     findElements(this.el, '.fc-button').forEach((buttonEl) => {
-      if (buttonName && buttonEl.classList.contains('.fc-' + buttonName + '-button')) {
+      if (buttonName && buttonEl.classList.contains('fc-' + buttonName + '-button')) {
         buttonEl.classList.add(className)
       } else {
         buttonEl.classList.remove(className)

+ 1 - 1
src/View.ts

@@ -250,7 +250,7 @@ export default abstract class View extends DateComponent {
 
 
   updateHeight(totalHeight, isAuto, isResize) {
-    super.updateSize(isResize)
+    this.updateSize(isResize)
   }
 
 

+ 13 - 4
src/agenda/AgendaView.ts

@@ -19,7 +19,7 @@ import reselector from '../util/reselector'
 import { EventUiHash, hasBgRendering } from '../component/event-rendering'
 import { buildGotoAnchorHtml, getAllDayHtml } from '../component/date-rendering'
 import { DateComponentProps } from '../component/DateComponent'
-import { DateMarker } from 'src/datelib/marker'
+import { DateMarker } from '../datelib/marker'
 
 const AGENDA_ALL_DAY_EVENT_LIMIT = 5
 const WEEK_HEADER_FORMAT = createFormatter({ week: 'short' })
@@ -145,7 +145,7 @@ export default class AgendaView extends View {
         '<tbody class="fc-body">' +
           '<tr>' +
             '<td class="' + theme.getClass('widgetContent') + '">' +
-              (this.dayGrid ?
+              (this.opt('allDaySlot') ?
                 '<div class="fc-day-grid"></div>' +
                 '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' :
                 ''
@@ -230,8 +230,8 @@ export default class AgendaView extends View {
 
 
   // Adjusts the vertical dimensions of the view to the specified values
-  updateHeight(totalHeight, isAuto, force) {
-    super.updateHeight(totalHeight, isAuto, force)
+  updateHeight(totalHeight, isAuto, isResize) {
+    super.updateHeight(totalHeight, isAuto, isResize)
 
     let eventLimit
     let scrollerHeight
@@ -304,6 +304,15 @@ export default class AgendaView extends View {
   }
 
 
+  updateSize(isResize: boolean) {
+    this.timeGrid.updateSize(isResize)
+
+    if (this.dayGrid) {
+      this.dayGrid.updateSize(isResize)
+    }
+  }
+
+
   // given a desired total height of the view, returns what the height of the scroller should be
   computeScrollerHeight(totalHeight) {
     return totalHeight -

+ 11 - 9
src/agenda/TimeGrid.ts

@@ -43,11 +43,6 @@ export default class TimeGrid extends DateComponent {
   bookendCells: DayTableInterface['bookendCells']
   getCellDate: DayTableInterface['getCellDate']
 
-  isInteractable = true
-  doesDragMirror = true
-  doesDragHighlight = false
-  slicingType: 'timed' = 'timed' // stupid TypeScript
-
   mirrorRenderer: any
 
   dayRanges: DateRange[] // of start-end of each day
@@ -655,10 +650,12 @@ export default class TimeGrid extends DateComponent {
 
   // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
   renderDateSelection(selection: DateSpan) {
-    if (this.opt('selectMirror')) {
-      this.mirrorRenderer.renderEventSegs(this.selectionToSegs(selection, true))
-    } else {
-      this.renderHighlightSegs(this.selectionToSegs(selection, false))
+    if (selection) {
+      if (this.opt('selectMirror')) {
+        this.mirrorRenderer.renderEventSegs(this.selectionToSegs(selection, true))
+      } else {
+        this.renderHighlightSegs(this.selectionToSegs(selection, false))
+      }
     }
   }
 
@@ -671,6 +668,11 @@ export default class TimeGrid extends DateComponent {
 
 }
 
+TimeGrid.prototype.isInteractable = true
+TimeGrid.prototype.doesDragMirror = true
+TimeGrid.prototype.doesDragHighlight = false
+TimeGrid.prototype.slicingType = 'timed'
+
 TimeGrid.prototype.eventRendererClass = TimeGridEventRenderer
 TimeGrid.prototype.mirrorRendererClass = TimeGridMirrorRenderer
 TimeGrid.prototype.fillRendererClass = TimeGridFillRenderer

+ 9 - 4
src/basic/BasicView.ts

@@ -151,14 +151,14 @@ export default class BasicView extends View {
 
 
   // Refreshes the horizontal dimensions of the view
-  updateHeight(totalHeight, isAuto, force) {
-    super.updateHeight(totalHeight, isAuto, force)
+  updateHeight(totalHeight, isAuto, isResize) {
+    super.updateHeight(totalHeight, isAuto, isResize)
 
     let { dayGrid } = this
     let eventLimit = this.opt('eventLimit')
     let headRowEl =
-      dayGrid.headContainerEl ?
-        dayGrid.headContainerEl.querySelector('.fc-row') as HTMLElement :
+      dayGrid.headerContainerEl ?
+        dayGrid.headerContainerEl.querySelector('.fc-row') as HTMLElement :
         null
     let scrollerHeight
     let scrollbarWidths
@@ -226,6 +226,11 @@ export default class BasicView extends View {
   }
 
 
+  updateSize(isResize: boolean) {
+    this.dayGrid.updateSize(isResize)
+  }
+
+
   // given a desired total height of the view, returns what the height of the scroller should be
   computeScrollerHeight(totalHeight) {
     return totalHeight -

+ 15 - 8
src/basic/DayGrid.ts

@@ -48,11 +48,6 @@ export default class DayGrid extends DateComponent {
   bookendCells: DayTableInterface['bookendCells']
   breakOnWeeks: DayTableInterface['breakOnWeeks']
 
-  isInteractable = true
-  doesDragMirror = false
-  doesDragHighlight = true
-  slicingType: 'all-day' = 'all-day' // stupid TypeScript
-
   view: View // TODO: make more general and/or remove
   mirrorRenderer: any
 
@@ -60,7 +55,7 @@ export default class DayGrid extends DateComponent {
 
   bottomCoordPadding: number = 0 // hack for extending the hit area for the last row of the coordinate grid
 
-  headContainerEl: HTMLElement // div that hold's the date header
+  headerContainerEl: HTMLElement // div that hold's the date header
   rowEls: HTMLElement[] // set of fake row elements
   cellEls: HTMLElement[] // set of whole-day elements comprising the row's background
 
@@ -76,6 +71,13 @@ export default class DayGrid extends DateComponent {
   segPopoverTile: DayTile
 
 
+  constructor(context, headerContainerEl, el) {
+    super(context, el)
+
+    this.headerContainerEl = headerContainerEl
+  }
+
+
   // Slices up the given span (unzoned start/end with other misc data) into an array of segments
   rangeToSegs(range: DateRange): Seg[] {
     range = intersectRanges(range, this.props.dateProfile.validRange)
@@ -127,8 +129,8 @@ export default class DayGrid extends DateComponent {
     let row
     let col
 
-    if (this.headContainerEl) {
-      this.headContainerEl.innerHTML = this.renderHeadHtml()
+    if (this.headerContainerEl) {
+      this.headerContainerEl.innerHTML = this.renderHeadHtml()
     }
 
     for (row = 0; row < rowCnt; row++) {
@@ -741,6 +743,11 @@ export default class DayGrid extends DateComponent {
 
 }
 
+DayGrid.prototype.isInteractable = true
+DayGrid.prototype.doesDragMirror = false
+DayGrid.prototype.doesDragHighlight = true
+DayGrid.prototype.slicingType = 'all-day'
+
 DayGrid.prototype.eventRendererClass = DayGridEventRenderer
 DayGrid.prototype.mirrorRendererClass = DayGridMirrorRenderer
 DayGrid.prototype.fillRendererClass = DayGridFillRenderer

+ 3 - 2
src/basic/DayTile.ts

@@ -11,8 +11,6 @@ import { ComponentContext } from '../component/Component'
 
 export default class DayTile extends DateComponent {
 
-  isInteractable = true
-  useEventCenter = false
   date: Date
   segContainerEl: HTMLElement
   width: number
@@ -114,4 +112,7 @@ export class DayTileEventRenderer extends DayGridEventRenderer {
 
 }
 
+DayTile.prototype.isInteractable = true
+DayTile.prototype.useEventCenter = false
+
 DayTile.prototype.eventRendererClass = DayTileEventRenderer

+ 8 - 6
src/component/Component.ts

@@ -74,7 +74,7 @@ export default class Component<PropsType> {
     if (!prevArgs || !isArraysEqual(prevArgs, args)) {
 
       if (prevArgs && unrenderMethodName) {
-        this[unrenderMethodName]()
+        this[unrenderMethodName].apply(this, prevArgs)
       }
 
       this[renderMethodName].apply(this, args)
@@ -109,17 +109,19 @@ export default class Component<PropsType> {
 
   // after destroy is called, this component won't ever be used again
   destroy() {
+    let { renderArgs } = this
+
     if (this.props) {
       this.unrender()
     }
 
-    let methodNames = [] // in reverse
-    this.unrenderMethodNames.forEach(function(methodName) {
-      methodNames.unshift(methodName)
+    let tuples = [] // in reverse
+    this.unrenderMethodNames.forEach(function(unrenderMethodName, renderMethodName) {
+      tuples.unshift([ unrenderMethodName, renderMethodName ])
     })
 
-    for (let methodName in methodNames) {
-      this[methodName]()
+    for (let tuple of tuples) {
+      this[tuple[0]].apply(this, renderArgs[tuple[1]])
     }
   }
 

+ 80 - 61
src/component/DateComponent.ts

@@ -40,21 +40,20 @@ export interface Seg {
 
 export default class DateComponent extends Component<DateComponentProps> {
 
-  // self-config, overridable by subclasses
-  isInteractable: boolean = false
-  useEventCenter: boolean = true // for dragging geometry
-  doesDragMirror: boolean = false // for events that ORIGINATE from this component
-  doesDragHighlight: boolean = false // for events that ORIGINATE from this component
-  fgSegSelector: string = '.fc-event-container > *' // lets eventRender produce elements without fc-event class
-  bgSegSelector: string = '.fc-bgevent'
+  // self-config, overridable by subclasses. must set on prototype
+  isInteractable: boolean
+  useEventCenter: boolean // for dragging geometry
+  doesDragMirror: boolean // for events that ORIGINATE from this component
+  doesDragHighlight: boolean // for events that ORIGINATE from this component
+  slicingType: 'timed' | 'all-day' | null
+  fgSegSelector: string // lets eventRender produce elements without fc-event class
+  bgSegSelector: string
 
   // if defined, holds the unit identified (ex: "year" or "month") that determines the level of granularity
   // of the date areas. if not defined, assumes to be day and time granularity.
   // TODO: port isTimeScale into same system?
   largeUnit: any
 
-  slicingType: 'timed' | 'all-day' | null = null
-
   eventRendererClass: any
   mirrorRendererClass: any
   fillRendererClass: any
@@ -105,51 +104,49 @@ export default class DateComponent extends Component<DateComponentProps> {
   }
 
   render(props: DateComponentProps) {
-    this.subrender('afterSkeletonRender', [], 'beforeSkeletonUnrender', 'skeleton')
-    let dateId = this.subrender('_renderDates', [ props.dateProfile ], '_unrenderDates', 'dates')
-    this.subrender('renderBusinessHours', [ props.businessHours, dateId ], 'unrenderBusinessHours', 'businessHours')
-    this.subrender('renderDateSelection', [ props.dateSelection, dateId ], 'unrenderDateSelection', 'dateSelection')
-    let evId = this.subrender('renderEvents', [ props.eventStore, props.eventUis, dateId ], 'unrenderEvents', 'events')
-    this.subrender('selectEventsByInstanceId', [ props.eventSelection, evId ], 'unselectAllEvents', 'eventSelection')
-    this.subrender('renderEventDragState', [ props.eventDrag, dateId ], 'unrenderEventDragState', 'eventDrag')
-    this.subrender('renderEventResizeState', [ props.eventResize, dateId ], 'unrenderEventResizeState', 'eventResize')
+    this.subrender('afterSkeletonRender', [], 'beforeSkeletonUnrender', true)
+    let dateId = this.subrender('_renderDates', [ props.dateProfile ], '_unrenderDates', true)
+    this.subrender('renderBusinessHours', [ props.businessHours, dateId ], 'unrenderBusinessHours', true)
+    this.subrender('renderDateSelection', [ props.dateSelection, dateId ], 'unrenderDateSelection', true)
+    let evId = this.subrender('renderEvents', [ props.eventStore, props.eventUis, dateId ], 'unrenderEvents', true)
+    this.subrender('selectEventsByInstanceId', [ props.eventSelection, evId ], 'unselectAllEvents', true)
+    this.subrender('renderEventDragState', [ props.eventDrag, dateId ], 'unrenderEventDragState', true)
+    this.subrender('renderEventResizeState', [ props.eventResize, dateId ], 'unrenderEventResizeState', true)
   }
 
   updateSize(isResize: boolean = false) {
-
-    // instead of using this hash as method names, uses it as flags
     let map = this.dirtySizeMethodNames
 
-    if (isResize || map.has('skeleton') || map.has('dates') || map.has('events')) {
+    if (isResize || map.has('afterSkeletonRender') || map.has('_renderDates') || map.has('renderEvents')) {
       // sort of the catch-all sizing
       // anything that might cause dimension changes
       this.updateBaseSize()
       this.buildPositionCaches()
     }
 
-    if (isResize || map.has('businessHours')) {
+    if (isResize || map.has('renderBusinessHours')) {
       this.computeBusinessHoursSize()
     }
 
-    if (isResize || map.has('dateSelection') || map.has('eventDrag') || map.has('eventResize')) {
+    if (isResize || map.has('renderDateSelection') || map.has('renderEventDragState') || map.has('renderEventResizeState')) {
       this.computeHighlightSize()
       this.computeMirrorSize()
     }
 
-    if (isResize || map.has('events')) {
+    if (isResize || map.has('renderEvents')) {
       this.computeEventsSize()
     }
 
-    if (isResize || map.has('businessHours')) {
+    if (isResize || map.has('renderBusinessHours')) {
       this.assignBusinessHoursSize()
     }
 
-    if (isResize || map.has('dateSelection') || map.has('eventDrag') || map.has('eventResize')) {
+    if (isResize || map.has('renderDateSelection') || map.has('renderEventDragState') || map.has('renderEventResizeState')) {
       this.assignHighlightSize()
       this.assignMirrorSize()
     }
 
-    if (isResize || map.has('events')) {
+    if (isResize || map.has('renderEvents')) {
       this.assignEventsSize()
     }
 
@@ -255,7 +252,9 @@ export default class DateComponent extends Component<DateComponentProps> {
   // ---------------------------------------------------------------------------------------------------------------
 
   renderDateSelection(selection: DateSpan) {
-    this.renderHighlightSegs(this.selectionToSegs(selection, false))
+    if (selection) {
+      this.renderHighlightSegs(this.selectionToSegs(selection, false))
+    }
   }
 
   unrenderDateSelection() {
@@ -319,23 +318,27 @@ export default class DateComponent extends Component<DateComponentProps> {
   // TODO: show/hide according to groupId?
 
   selectEventsByInstanceId(instanceId) {
-    this.getAllEventSegs().forEach(function(seg) {
-      let eventInstance = seg.eventRange.instance
-      if (
-        eventInstance && eventInstance.instanceId === instanceId &&
-        seg.el // necessary?
-      ) {
-        seg.el.classList.add('fc-selected')
-      }
-    })
+    if (instanceId) {
+      this.getAllEventSegs().forEach(function(seg) {
+        let eventInstance = seg.eventRange.instance
+        if (
+          eventInstance && eventInstance.instanceId === instanceId &&
+          seg.el // necessary?
+        ) {
+          seg.el.classList.add('fc-selected')
+        }
+      })
+    }
   }
 
-  unselectAllEvents() {
-    this.getAllEventSegs().forEach(function(seg) {
-      if (seg.el) { // necessary?
-        seg.el.classList.remove('fc-selected')
-      }
-    })
+  unselectAllEvents(instanceId) {
+    if (instanceId) {
+      this.getAllEventSegs().forEach(function(seg) {
+        if (seg.el) { // necessary?
+          seg.el.classList.remove('fc-selected')
+        }
+      })
+    }
   }
 
 
@@ -343,18 +346,22 @@ export default class DateComponent extends Component<DateComponentProps> {
   // ---------------------------------------------------------------------------------------------------------------
 
   renderEventDragState(state: EventInteractionUiState) {
-    this.hideSegsByHash(state.affectedEvents.instances)
-    this.renderEventDrag(
-      state.mutatedEvents,
-      state.eventUis,
-      state.isEvent,
-      state.origSeg
-    )
+    if (state) {
+      this.hideSegsByHash(state.affectedEvents.instances)
+      this.renderEventDrag(
+        state.mutatedEvents,
+        state.eventUis,
+        state.isEvent,
+        state.origSeg
+      )
+    }
   }
 
-  unrenderEventDragState() {
-    this.showSegsByHash(this.props.eventDrag.affectedEvents.instances)
-    this.unrenderEventDrag()
+  unrenderEventDragState(state: EventInteractionUiState) {
+    if (state) {
+      this.showSegsByHash(state.affectedEvents.instances)
+      this.unrenderEventDrag()
+    }
   }
 
   // Renders a visual indication of a event or external-element drag over the given drop zone.
@@ -394,17 +401,21 @@ export default class DateComponent extends Component<DateComponentProps> {
   // ---------------------------------------------------------------------------------------------------------------
 
   renderEventResizeState(state: EventInteractionUiState) {
-    this.hideSegsByHash(state.affectedEvents.instances)
-    this.renderEventResize(
-      state.mutatedEvents,
-      state.eventUis,
-      state.origSeg
-    )
+    if (state) {
+      this.hideSegsByHash(state.affectedEvents.instances)
+      this.renderEventResize(
+        state.mutatedEvents,
+        state.eventUis,
+        state.origSeg
+      )
+    }
   }
 
-  unrenderEventResizeState() {
-    this.showSegsByHash(this.props.eventResize.affectedEvents.instances)
-    this.unrenderEventResize()
+  unrenderEventResizeState(state: EventInteractionUiState) {
+    if (state) {
+      this.showSegsByHash(state.affectedEvents.instances)
+      this.unrenderEventResize()
+    }
   }
 
   // Renders a visual indication of an event being resized.
@@ -722,3 +733,11 @@ export default class DateComponent extends Component<DateComponentProps> {
   }
 
 }
+
+DateComponent.prototype.isInteractable = false
+DateComponent.prototype.useEventCenter = true
+DateComponent.prototype.doesDragMirror = false
+DateComponent.prototype.doesDragHighlight = false
+DateComponent.prototype.slicingType = null
+DateComponent.prototype.fgSegSelector = '.fc-event-container > *'
+DateComponent.prototype.bgSegSelector = '.fc-bgevent'

+ 6 - 6
src/component/DayTableMixin.ts

@@ -43,7 +43,7 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
   updateDayTable() {
     let t = (this as any)
     let view = t.view as View
-    let dateProfile = t.dateProfile
+    let dateProfile = t.props.dateProfile
     let date: DateMarker = dateProfile.renderRange.start
     let end: DateMarker = dateProfile.renderRange.end
     let dayIndex = -1
@@ -273,7 +273,7 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
 
 
   renderHeadHtml() {
-    let theme = (this as any).getTheme()
+    let theme = (this as any).theme
 
     return '' +
       '<div class="fc-row ' + theme.getClass('headerRow') + '">' +
@@ -320,8 +320,8 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
   renderHeadDateCellHtml(date: DateMarker, colspan, otherAttrs) {
     let t = (this as any)
     let view = t.view
-    let dateEnv = t.getDateEnv()
-    let dateProfile = t.dateProfile
+    let dateEnv = t.dateEnv
+    let dateProfile = t.props.dateProfile
     let isDateValid = rangeContainsMarker(dateProfile.activeRange, date) // TODO: called too frequently. cache somehow.
     let classNames = [
       'fc-day-header',
@@ -412,8 +412,8 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
   renderBgCellHtml(date: DateMarker, otherAttrs) {
     let t = (this as any)
     let view = t.view
-    let dateEnv = t.getDateEnv()
-    let dateProfile = t.dateProfile
+    let dateEnv = t.dateEnv
+    let dateProfile = t.props.dateProfile
     let isDateValid = rangeContainsMarker(dateProfile.activeRange, date) // TODO: called too frequently. cache somehow.
     let classes = getDayClasses(t, date)
 

+ 7 - 6
src/component/date-rendering.ts

@@ -60,21 +60,22 @@ export function getAllDayHtml(component: Component<any>) {
 
 // Computes HTML classNames for a single-day element
 export function getDayClasses(component: DateComponent, date: DateMarker, noThemeHighlight?) {
-  let view = this.view
+  let { calendar, view, theme } = component
+  let dateProfile = component.props.dateProfile
   let classes = []
   let todayStart: DateMarker
   let todayEnd: DateMarker
 
-  if (!rangeContainsMarker(this.dateProfile.activeRange, date)) {
-    classes.push('fc-disabled-day') // TODO: jQuery UI theme?
+  if (!rangeContainsMarker(dateProfile.activeRange, date)) {
+    classes.push('fc-disabled-day')
   } else {
     classes.push('fc-' + DAY_IDS[date.getUTCDay()])
 
-    if (view.isDateInOtherMonth(date, this.dateProfile)) { // TODO: use DateComponent subclass somehow
+    if (view.isDateInOtherMonth(date, dateProfile)) {
       classes.push('fc-other-month')
     }
 
-    todayStart = startOfDay(view.calendar.getNow())
+    todayStart = startOfDay(calendar.getNow())
     todayEnd = addDays(todayStart, 1)
 
     if (date < todayStart) {
@@ -85,7 +86,7 @@ export function getDayClasses(component: DateComponent, date: DateMarker, noThem
       classes.push('fc-today')
 
       if (noThemeHighlight !== true) {
-        classes.push(view.calendar.theme.getClass('today'))
+        classes.push(theme.getClass('today'))
       }
     }
   }

+ 1 - 1
src/component/renderers/EventRenderer.ts

@@ -25,7 +25,7 @@ export default class EventRenderer {
 
 
   constructor(component, fillRenderer) { // fillRenderer is optional
-    this.view = component.view
+    this.view = component.view || component
     this.component = component
     this.fillRenderer = fillRenderer
   }

+ 1 - 1
src/component/renderers/MirrorRenderer.ts

@@ -12,7 +12,7 @@ export default abstract class MirrorRenderer {
 
 
   constructor(component, eventRenderer) {
-    this.view = component.view
+    this.view = component.view || component
     this.component = component
     this.eventRenderer = eventRenderer
   }

+ 5 - 9
src/list/ListView.ts

@@ -15,13 +15,6 @@ Responsible for the scroller, and forwarding event-related actions into the "gri
 */
 export default class ListView extends View {
 
-  // initialized after the class
-  eventRendererClass: any
-
-  isInteractable = true
-  slicingType: 'all-day' = 'all-day' // stupid TypeScript
-  fgSegSelector: any = '.fc-list-item' // which elements accept event actions
-
   scroller: ScrollComponent
   contentEl: HTMLElement
 
@@ -55,8 +48,8 @@ export default class ListView extends View {
   }
 
 
-  updateHeight(totalHeight, isAuto, force) {
-    super.updateHeight(totalHeight, isAuto, force)
+  updateHeight(totalHeight, isAuto, isResize) {
+    super.updateHeight(totalHeight, isAuto, isResize)
 
     this.scroller.clear() // sets height to 'auto' and clears overflow
 
@@ -236,3 +229,6 @@ export default class ListView extends View {
 }
 
 ListView.prototype.eventRendererClass = ListEventRenderer
+ListView.prototype.isInteractable = true
+ListView.prototype.slicingType = 'all-day'
+ListView.prototype.fgSegSelector = '.fc-list-item' // which elements accept event actions

+ 1 - 0
src/list/config.ts

@@ -3,6 +3,7 @@ import ListView from './ListView'
 
 defineView('list', {
   class: ListView,
+  buttonTextKey: 'list', // what to lookup in locale files
   listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
 })
 

+ 6 - 2
src/reducers/main.ts

@@ -56,7 +56,11 @@ function reduceDateProfile(currentDateProfile: DateProfile | null, action: Actio
     case 'SET_DATE':
     case 'SET_VIEW_TYPE':
       return protectSameDateProfile(
-        calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true), // forceToValid=true
+        calendar.dateProfileGenerators[viewType].build(
+          action.dateMarker || currentDateProfile.currentDate,
+          undefined,
+          true // forceToValid=true
+        ),
         currentDateProfile
       )
     default:
@@ -139,7 +143,7 @@ function reduceEventResize(currentResize: EventInteractionUiState | null, action
 }
 
 function protectSameDateProfile(newDateProfile, oldDateProfile) {
-  if (isDateProfilesEqual(newDateProfile, oldDateProfile)) {
+  if (newDateProfile && oldDateProfile && isDateProfilesEqual(newDateProfile, oldDateProfile)) {
     return oldDateProfile
   }
 

+ 12 - 6
src/structs/view-spec.ts

@@ -67,13 +67,19 @@ function buildViewSpec(viewDef: ViewDef, overrideConfigs: ViewConfigHash, option
   }
 
   let queryButtonText = function(options) {
-    let buttonText = options.buttonText || {}
+    let buttonTextMap = options.buttonText || {}
+    let buttonTextKey = viewDef.defaults.buttonTextKey
 
-    if (buttonText[viewDef.type] != null) {
-      return buttonText[viewDef.type]
+    if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
+      return buttonTextMap[buttonTextKey]
     }
-    if (buttonText[singleUnit] != null) {
-      return buttonText[singleUnit]
+
+    if (buttonTextMap[viewDef.type] != null) {
+      return buttonTextMap[viewDef.type]
+    }
+
+    if (buttonTextMap[singleUnit] != null) {
+      return buttonTextMap[singleUnit]
     }
   }
 
@@ -104,7 +110,7 @@ function buildViewSpec(viewDef: ViewDef, overrideConfigs: ViewConfigHash, option
     buttonTextDefault:
       queryButtonText(optionsManager.localeDefaults) ||
       queryButtonText(optionsManager.dirDefaults) ||
-      viewDef.defaults.buttonText || // a single string. from ViewSubclass.defaults
+      viewDef.defaults.buttonText ||
       queryButtonText(globalDefaults) ||
       viewDef.type // fall back to given view name
   }