Skip to content

Commit

Permalink
attempt resetOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Mar 26, 2019
1 parent 9d57cc5 commit 60d2d15
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 15 deletions.
86 changes: 73 additions & 13 deletions src/core/Calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Duration, createDuration } from './datelib/duration'
import reduce from './reducers/main'
import { parseDateSpan, DateSpanInput, DateSpan, buildDateSpanApi, DateSpanApi, buildDatePointApi, DatePointApi } from './structs/date-span'
import { memoize, memoizeOutput } from './util/memoize'
import { mapHash, isPropsEqual } from './util/object'
import { mapHash, isPropsEqual, anyKeysRemoved, computeChangedProps } from './util/object'
import { DateRangeInput } from './datelib/date-range'
import DateProfileGenerator from './DateProfileGenerator'
import { EventSourceInput, parseEventSource, EventSourceHash } from './structs/event-source'
Expand Down Expand Up @@ -54,6 +54,15 @@ export type DateSpanTransform = (dateSpan: DateSpan, calendar: Calendar) => any
export type CalendarInteraction = { destroy() }
export type CalendarInteractionClass = { new(calendar: Calendar): CalendarInteraction }

const SPECIAL_OPTIONS = {
events(events, calendar) {
console.log('handle events', events, calendar)
},
eventSources(eventSources, calendar) {
console.log('handle eventSources', eventSources, calendar)
}
}

export default class Calendar {

// global handler registry
Expand Down Expand Up @@ -481,23 +490,72 @@ export default class Calendar {
// -----------------------------------------------------------------------------------------------------------------


setOption(name: string, value: any) {
let oldDateEnv = this.dateEnv
setOption(name: string, val) {
this._setOptions({ [name]: val }, 'dynamic')
}

this.optionsManager.add(name, value)
this.handleOptions(this.optionsManager.computed)

if (name === 'height' || name === 'contentHeight' || name === 'aspectRatio') {
this.updateSize()
} else if (name === 'defaultDate' || name === 'defaultView') {
// can't change date this way. use gotoDate instead
} else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(name)) {
// doesn't affect rendering. only interactions.
// not for public use
resetOptions(options) {
let oldOptions = this.optionsManager.overrides
let normalOptions = {}
let specialOptions = {}

for (let name in options) {
if (SPECIAL_OPTIONS[name]) {
specialOptions[name] = options[name]
} else {
normalOptions[name] = options[name]
}
}

if (anyKeysRemoved(oldOptions, normalOptions)) {
this._setOptions(options, 'reset')
} else {
this._setOptions(computeChangedProps(oldOptions, options))
}

// handle special options last
for (let name in specialOptions) {
SPECIAL_OPTIONS[name](specialOptions[name], this)
}
}


_setOptions(options, mode?: 'dynamic' | 'reset') {
let oldDateEnv = this.dateEnv // do this before handleOptions
let isTimeZoneDirty = false
let isSizeDirty = true
let needsFullRerender = false

for (let name in options) {
if (/^(height|contentHeight|aspectRatio)$/.test(name)) {
isSizeDirty = true
} else if (/^(defaultDate|defaultView)$/.test(name)) {
// can't change date this way. use gotoDate instead
} else if (name === 'timeZone') {
isTimeZoneDirty = true
} else {
needsFullRerender = true
}
}

if (mode === 'reset') {
needsFullRerender = true
this.optionsManager.reset(options)
} else if (mode === 'dynamic') {
this.optionsManager.addDynamic(options) // takes higher precedence
} else {
this.optionsManager.add(options)
}

this.handleOptions(this.optionsManager.computed)

if (needsFullRerender) {
this.needsFullRerender = true
this.batchRendering(() => {

if (name === 'timeZone') {
if (isTimeZoneDirty) {
this.dispatch({
type: 'CHANGE_TIMEZONE',
oldDateEnv
Expand All @@ -513,6 +571,8 @@ export default class Calendar {
viewType: this.state.viewType
})
})
} if (isSizeDirty) {
this.updateSize()
}
}

Expand Down Expand Up @@ -648,7 +708,7 @@ export default class Calendar {

if (dateOrRange) {
if ((dateOrRange as DateRangeInput).start && (dateOrRange as DateRangeInput).end) { // a range
this.optionsManager.add('visibleRange', dateOrRange) // will not rerender
this.optionsManager.addDynamic({ visibleRange: dateOrRange }) // will not rerender
this.handleOptions(this.optionsManager.computed) // ...but yuck
} else { // a date
dateMarker = this.dateEnv.createMarker(dateOrRange as DateInput) // just like gotoDate
Expand Down
18 changes: 16 additions & 2 deletions src/core/OptionsManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { firstDefined } from './util/misc'
import { globalDefaults, rtlDefaults, mergeOptions } from './options'
import { parseRawLocales, buildLocale } from './datelib/locale'
import { __assign } from 'tslib'


export default class OptionsManager {
Expand All @@ -19,8 +20,21 @@ export default class OptionsManager {
}


add(name, value) {
this.dynamicOverrides[name] = value
add(props) {
__assign(this.overrides, props)
this.compute()
}


addDynamic(props) {
__assign(this.dynamicOverrides, props)
this.compute()
}


reset(props) {
this.overrides = props
this.dynamicOverrides = {}
this.compute()
}

Expand Down
37 changes: 37 additions & 0 deletions src/core/util/object.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isArraysEqual } from './array'

// Merges an array of objects into a single object.
// The second argument allows for an array of property names who's object values will be merged together.
Expand Down Expand Up @@ -103,3 +104,39 @@ export function isPropsEqual(obj0, obj1): boolean {

return true
}


export function anyKeysRemoved(obj0, obj1) {
for (let prop in obj0) {
if (!(prop in obj1)) {
return true
}
}
return false
}

// will go recursively one level deep
export function computeChangedProps(obj0, obj1) {
let res = {}

for (let prop in obj1) {

if (!(prop in obj0)) {
res[prop] = obj1[prop]

} else {
let val0 = obj0[prop]
let val1 = obj1[prop]

if (
val0 !== val1 &&
!(Array.isArray(val0) && Array.isArray(val1) && isArraysEqual(val0, val1)) &&
!(typeof val0 === 'object' && typeof val1 === 'object' && isPropsEqual(val0, val1))
) {
res[prop] = val1
}
}
}

return res
}

0 comments on commit 60d2d15

Please sign in to comment.