2019-08-28 10:59:33 +00:00
/ * !
2020-06-01 11:05:25 +00:00
FullCalendar Core Package v4 . 4.2
2019-08-28 10:59:33 +00:00
Docs & License : https : //fullcalendar.io/
( c ) 2019 Adam Shaw
* /
// Creating
// ----------------------------------------------------------------------------------------------------------------
var elementPropHash = {
className : true ,
colSpan : true ,
rowSpan : true
} ;
var containerTagHash = {
'<tr' : 'tbody' ,
'<td' : 'tr'
} ;
function createElement ( tagName , attrs , content ) {
var el = document . createElement ( tagName ) ;
if ( attrs ) {
for ( var attrName in attrs ) {
if ( attrName === 'style' ) {
applyStyle ( el , attrs [ attrName ] ) ;
}
else if ( elementPropHash [ attrName ] ) {
el [ attrName ] = attrs [ attrName ] ;
}
else {
el . setAttribute ( attrName , attrs [ attrName ] ) ;
}
}
}
if ( typeof content === 'string' ) {
el . innerHTML = content ; // shortcut. no need to process HTML in any way
}
else if ( content != null ) {
appendToElement ( el , content ) ;
}
return el ;
}
function htmlToElement ( html ) {
html = html . trim ( ) ;
var container = document . createElement ( computeContainerTag ( html ) ) ;
container . innerHTML = html ;
return container . firstChild ;
}
function htmlToElements ( html ) {
return Array . prototype . slice . call ( htmlToNodeList ( html ) ) ;
}
function htmlToNodeList ( html ) {
html = html . trim ( ) ;
var container = document . createElement ( computeContainerTag ( html ) ) ;
container . innerHTML = html ;
return container . childNodes ;
}
// assumes html already trimmed and tag names are lowercase
function computeContainerTag ( html ) {
return containerTagHash [ html . substr ( 0 , 3 ) // faster than using regex
] || 'div' ;
}
function appendToElement ( el , content ) {
var childNodes = normalizeContent ( content ) ;
for ( var i = 0 ; i < childNodes . length ; i ++ ) {
el . appendChild ( childNodes [ i ] ) ;
}
}
function prependToElement ( parent , content ) {
var newEls = normalizeContent ( content ) ;
var afterEl = parent . firstChild || null ; // if no firstChild, will append to end, but that's okay, b/c there were no children
for ( var i = 0 ; i < newEls . length ; i ++ ) {
parent . insertBefore ( newEls [ i ] , afterEl ) ;
}
}
function insertAfterElement ( refEl , content ) {
var newEls = normalizeContent ( content ) ;
var afterEl = refEl . nextSibling || null ;
for ( var i = 0 ; i < newEls . length ; i ++ ) {
refEl . parentNode . insertBefore ( newEls [ i ] , afterEl ) ;
}
}
function normalizeContent ( content ) {
var els ;
if ( typeof content === 'string' ) {
els = htmlToElements ( content ) ;
}
else if ( content instanceof Node ) {
els = [ content ] ;
}
else { // Node[] or NodeList
els = Array . prototype . slice . call ( content ) ;
}
return els ;
}
function removeElement ( el ) {
if ( el . parentNode ) {
el . parentNode . removeChild ( el ) ;
}
}
// Querying
// ----------------------------------------------------------------------------------------------------------------
// from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
var matchesMethod = Element . prototype . matches ||
Element . prototype . matchesSelector ||
Element . prototype . msMatchesSelector ;
var closestMethod = Element . prototype . closest || function ( selector ) {
// polyfill
var el = this ;
if ( ! document . documentElement . contains ( el ) ) {
return null ;
}
do {
if ( elementMatches ( el , selector ) ) {
return el ;
}
el = el . parentElement || el . parentNode ;
} while ( el !== null && el . nodeType === 1 ) ;
return null ;
} ;
function elementClosest ( el , selector ) {
return closestMethod . call ( el , selector ) ;
}
function elementMatches ( el , selector ) {
return matchesMethod . call ( el , selector ) ;
}
// accepts multiple subject els
// returns a real array. good for methods like forEach
function findElements ( container , selector ) {
var containers = container instanceof HTMLElement ? [ container ] : container ;
var allMatches = [ ] ;
for ( var i = 0 ; i < containers . length ; i ++ ) {
var matches = containers [ i ] . querySelectorAll ( selector ) ;
for ( var j = 0 ; j < matches . length ; j ++ ) {
allMatches . push ( matches [ j ] ) ;
}
}
return allMatches ;
}
// accepts multiple subject els
// only queries direct child elements
function findChildren ( parent , selector ) {
var parents = parent instanceof HTMLElement ? [ parent ] : parent ;
var allMatches = [ ] ;
for ( var i = 0 ; i < parents . length ; i ++ ) {
var childNodes = parents [ i ] . children ; // only ever elements
for ( var j = 0 ; j < childNodes . length ; j ++ ) {
var childNode = childNodes [ j ] ;
if ( ! selector || elementMatches ( childNode , selector ) ) {
allMatches . push ( childNode ) ;
}
}
}
return allMatches ;
}
// Attributes
// ----------------------------------------------------------------------------------------------------------------
function forceClassName ( el , className , bool ) {
if ( bool ) {
el . classList . add ( className ) ;
}
else {
el . classList . remove ( className ) ;
}
}
// Style
// ----------------------------------------------------------------------------------------------------------------
var PIXEL _PROP _RE = /(top|left|right|bottom|width|height)$/i ;
function applyStyle ( el , props ) {
for ( var propName in props ) {
applyStyleProp ( el , propName , props [ propName ] ) ;
}
}
function applyStyleProp ( el , name , val ) {
if ( val == null ) {
el . style [ name ] = '' ;
}
else if ( typeof val === 'number' && PIXEL _PROP _RE . test ( name ) ) {
el . style [ name ] = val + 'px' ;
}
else {
el . style [ name ] = val ;
}
}
function pointInsideRect ( point , rect ) {
return point . left >= rect . left &&
point . left < rect . right &&
point . top >= rect . top &&
point . top < rect . bottom ;
}
// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
function intersectRects ( rect1 , rect2 ) {
var res = {
left : Math . max ( rect1 . left , rect2 . left ) ,
right : Math . min ( rect1 . right , rect2 . right ) ,
top : Math . max ( rect1 . top , rect2 . top ) ,
bottom : Math . min ( rect1 . bottom , rect2 . bottom )
} ;
if ( res . left < res . right && res . top < res . bottom ) {
return res ;
}
return false ;
}
function translateRect ( rect , deltaX , deltaY ) {
return {
left : rect . left + deltaX ,
right : rect . right + deltaX ,
top : rect . top + deltaY ,
bottom : rect . bottom + deltaY
} ;
}
// Returns a new point that will have been moved to reside within the given rectangle
function constrainPoint ( point , rect ) {
return {
left : Math . min ( Math . max ( point . left , rect . left ) , rect . right ) ,
top : Math . min ( Math . max ( point . top , rect . top ) , rect . bottom )
} ;
}
// Returns a point that is the center of the given rectangle
function getRectCenter ( rect ) {
return {
left : ( rect . left + rect . right ) / 2 ,
top : ( rect . top + rect . bottom ) / 2
} ;
}
// Subtracts point2's coordinates from point1's coordinates, returning a delta
function diffPoints ( point1 , point2 ) {
return {
left : point1 . left - point2 . left ,
top : point1 . top - point2 . top
} ;
}
// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side
var isRtlScrollbarOnLeft = null ;
function getIsRtlScrollbarOnLeft ( ) {
if ( isRtlScrollbarOnLeft === null ) {
isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft ( ) ;
}
return isRtlScrollbarOnLeft ;
}
function computeIsRtlScrollbarOnLeft ( ) {
var outerEl = createElement ( 'div' , {
style : {
position : 'absolute' ,
top : - 1000 ,
left : 0 ,
border : 0 ,
padding : 0 ,
overflow : 'scroll' ,
direction : 'rtl'
}
} , '<div></div>' ) ;
document . body . appendChild ( outerEl ) ;
var innerEl = outerEl . firstChild ;
var res = innerEl . getBoundingClientRect ( ) . left > outerEl . getBoundingClientRect ( ) . left ;
removeElement ( outerEl ) ;
return res ;
}
// The scrollbar width computations in computeEdges are sometimes flawed when it comes to
// retina displays, rounding, and IE11. Massage them into a usable value.
function sanitizeScrollbarWidth ( width ) {
width = Math . max ( 0 , width ) ; // no negatives
width = Math . round ( width ) ;
return width ;
}
function computeEdges ( el , getPadding ) {
if ( getPadding === void 0 ) { getPadding = false ; }
var computedStyle = window . getComputedStyle ( el ) ;
var borderLeft = parseInt ( computedStyle . borderLeftWidth , 10 ) || 0 ;
var borderRight = parseInt ( computedStyle . borderRightWidth , 10 ) || 0 ;
var borderTop = parseInt ( computedStyle . borderTopWidth , 10 ) || 0 ;
var borderBottom = parseInt ( computedStyle . borderBottomWidth , 10 ) || 0 ;
// must use offset(Width|Height) because compatible with client(Width|Height)
var scrollbarLeftRight = sanitizeScrollbarWidth ( el . offsetWidth - el . clientWidth - borderLeft - borderRight ) ;
var scrollbarBottom = sanitizeScrollbarWidth ( el . offsetHeight - el . clientHeight - borderTop - borderBottom ) ;
var res = {
borderLeft : borderLeft ,
borderRight : borderRight ,
borderTop : borderTop ,
borderBottom : borderBottom ,
scrollbarBottom : scrollbarBottom ,
scrollbarLeft : 0 ,
scrollbarRight : 0
} ;
if ( getIsRtlScrollbarOnLeft ( ) && computedStyle . direction === 'rtl' ) { // is the scrollbar on the left side?
res . scrollbarLeft = scrollbarLeftRight ;
}
else {
res . scrollbarRight = scrollbarLeftRight ;
}
if ( getPadding ) {
res . paddingLeft = parseInt ( computedStyle . paddingLeft , 10 ) || 0 ;
res . paddingRight = parseInt ( computedStyle . paddingRight , 10 ) || 0 ;
res . paddingTop = parseInt ( computedStyle . paddingTop , 10 ) || 0 ;
res . paddingBottom = parseInt ( computedStyle . paddingBottom , 10 ) || 0 ;
}
return res ;
}
function computeInnerRect ( el , goWithinPadding ) {
if ( goWithinPadding === void 0 ) { goWithinPadding = false ; }
var outerRect = computeRect ( el ) ;
var edges = computeEdges ( el , goWithinPadding ) ;
var res = {
left : outerRect . left + edges . borderLeft + edges . scrollbarLeft ,
right : outerRect . right - edges . borderRight - edges . scrollbarRight ,
top : outerRect . top + edges . borderTop ,
bottom : outerRect . bottom - edges . borderBottom - edges . scrollbarBottom
} ;
if ( goWithinPadding ) {
res . left += edges . paddingLeft ;
res . right -= edges . paddingRight ;
res . top += edges . paddingTop ;
res . bottom -= edges . paddingBottom ;
}
return res ;
}
function computeRect ( el ) {
var rect = el . getBoundingClientRect ( ) ;
return {
left : rect . left + window . pageXOffset ,
top : rect . top + window . pageYOffset ,
right : rect . right + window . pageXOffset ,
bottom : rect . bottom + window . pageYOffset
} ;
}
function computeViewportRect ( ) {
return {
left : window . pageXOffset ,
right : window . pageXOffset + document . documentElement . clientWidth ,
top : window . pageYOffset ,
bottom : window . pageYOffset + document . documentElement . clientHeight
} ;
}
function computeHeightAndMargins ( el ) {
return el . getBoundingClientRect ( ) . height + computeVMargins ( el ) ;
}
function computeVMargins ( el ) {
var computed = window . getComputedStyle ( el ) ;
return parseInt ( computed . marginTop , 10 ) +
parseInt ( computed . marginBottom , 10 ) ;
}
// does not return window
function getClippingParents ( el ) {
var parents = [ ] ;
while ( el instanceof HTMLElement ) { // will stop when gets to document or null
var computedStyle = window . getComputedStyle ( el ) ;
if ( computedStyle . position === 'fixed' ) {
break ;
}
if ( ( /(auto|scroll)/ ) . test ( computedStyle . overflow + computedStyle . overflowY + computedStyle . overflowX ) ) {
parents . push ( el ) ;
}
el = el . parentNode ;
}
return parents ;
}
function computeClippingRect ( el ) {
return getClippingParents ( el )
. map ( function ( el ) {
return computeInnerRect ( el ) ;
} )
. concat ( computeViewportRect ( ) )
. reduce ( function ( rect0 , rect1 ) {
return intersectRects ( rect0 , rect1 ) || rect1 ; // should always intersect
} ) ;
}
// Stops a mouse/touch event from doing it's native browser action
function preventDefault ( ev ) {
ev . preventDefault ( ) ;
}
// Event Delegation
// ----------------------------------------------------------------------------------------------------------------
function listenBySelector ( container , eventType , selector , handler ) {
function realHandler ( ev ) {
var matchedChild = elementClosest ( ev . target , selector ) ;
if ( matchedChild ) {
handler . call ( matchedChild , ev , matchedChild ) ;
}
}
container . addEventListener ( eventType , realHandler ) ;
return function ( ) {
container . removeEventListener ( eventType , realHandler ) ;
} ;
}
function listenToHoverBySelector ( container , selector , onMouseEnter , onMouseLeave ) {
var currentMatchedChild ;
return listenBySelector ( container , 'mouseover' , selector , function ( ev , matchedChild ) {
if ( matchedChild !== currentMatchedChild ) {
currentMatchedChild = matchedChild ;
onMouseEnter ( ev , matchedChild ) ;
var realOnMouseLeave _1 = function ( ev ) {
currentMatchedChild = null ;
onMouseLeave ( ev , matchedChild ) ;
matchedChild . removeEventListener ( 'mouseleave' , realOnMouseLeave _1 ) ;
} ;
// listen to the next mouseleave, and then unattach
matchedChild . addEventListener ( 'mouseleave' , realOnMouseLeave _1 ) ;
}
} ) ;
}
// Animation
// ----------------------------------------------------------------------------------------------------------------
var transitionEventNames = [
'webkitTransitionEnd' ,
'otransitionend' ,
'oTransitionEnd' ,
'msTransitionEnd' ,
'transitionend'
] ;
// triggered only when the next single subsequent transition finishes
function whenTransitionDone ( el , callback ) {
var realCallback = function ( ev ) {
callback ( ev ) ;
transitionEventNames . forEach ( function ( eventName ) {
el . removeEventListener ( eventName , realCallback ) ;
} ) ;
} ;
transitionEventNames . forEach ( function ( eventName ) {
el . addEventListener ( eventName , realCallback ) ; // cross-browser way to determine when the transition finishes
} ) ;
}
var DAY _IDS = [ 'sun' , 'mon' , 'tue' , 'wed' , 'thu' , 'fri' , 'sat' ] ;
// Adding
function addWeeks ( m , n ) {
var a = dateToUtcArray ( m ) ;
a [ 2 ] += n * 7 ;
return arrayToUtcDate ( a ) ;
}
function addDays ( m , n ) {
var a = dateToUtcArray ( m ) ;
a [ 2 ] += n ;
return arrayToUtcDate ( a ) ;
}
function addMs ( m , n ) {
var a = dateToUtcArray ( m ) ;
a [ 6 ] += n ;
return arrayToUtcDate ( a ) ;
}
// Diffing (all return floats)
function diffWeeks ( m0 , m1 ) {
return diffDays ( m0 , m1 ) / 7 ;
}
function diffDays ( m0 , m1 ) {
return ( m1 . valueOf ( ) - m0 . valueOf ( ) ) / ( 1000 * 60 * 60 * 24 ) ;
}
function diffHours ( m0 , m1 ) {
return ( m1 . valueOf ( ) - m0 . valueOf ( ) ) / ( 1000 * 60 * 60 ) ;
}
function diffMinutes ( m0 , m1 ) {
return ( m1 . valueOf ( ) - m0 . valueOf ( ) ) / ( 1000 * 60 ) ;
}
function diffSeconds ( m0 , m1 ) {
return ( m1 . valueOf ( ) - m0 . valueOf ( ) ) / 1000 ;
}
function diffDayAndTime ( m0 , m1 ) {
var m0day = startOfDay ( m0 ) ;
var m1day = startOfDay ( m1 ) ;
return {
years : 0 ,
months : 0 ,
days : Math . round ( diffDays ( m0day , m1day ) ) ,
milliseconds : ( m1 . valueOf ( ) - m1day . valueOf ( ) ) - ( m0 . valueOf ( ) - m0day . valueOf ( ) )
} ;
}
// Diffing Whole Units
function diffWholeWeeks ( m0 , m1 ) {
var d = diffWholeDays ( m0 , m1 ) ;
if ( d !== null && d % 7 === 0 ) {
return d / 7 ;
}
return null ;
}
function diffWholeDays ( m0 , m1 ) {
if ( timeAsMs ( m0 ) === timeAsMs ( m1 ) ) {
return Math . round ( diffDays ( m0 , m1 ) ) ;
}
return null ;
}
// Start-Of
function startOfDay ( m ) {
return arrayToUtcDate ( [
m . getUTCFullYear ( ) ,
m . getUTCMonth ( ) ,
m . getUTCDate ( )
] ) ;
}
function startOfHour ( m ) {
return arrayToUtcDate ( [
m . getUTCFullYear ( ) ,
m . getUTCMonth ( ) ,
m . getUTCDate ( ) ,
m . getUTCHours ( )
] ) ;
}
function startOfMinute ( m ) {
return arrayToUtcDate ( [
m . getUTCFullYear ( ) ,
m . getUTCMonth ( ) ,
m . getUTCDate ( ) ,
m . getUTCHours ( ) ,
m . getUTCMinutes ( )
] ) ;
}
function startOfSecond ( m ) {
return arrayToUtcDate ( [
m . getUTCFullYear ( ) ,
m . getUTCMonth ( ) ,
m . getUTCDate ( ) ,
m . getUTCHours ( ) ,
m . getUTCMinutes ( ) ,
m . getUTCSeconds ( )
] ) ;
}
// Week Computation
function weekOfYear ( marker , dow , doy ) {
var y = marker . getUTCFullYear ( ) ;
var w = weekOfGivenYear ( marker , y , dow , doy ) ;
if ( w < 1 ) {
return weekOfGivenYear ( marker , y - 1 , dow , doy ) ;
}
var nextW = weekOfGivenYear ( marker , y + 1 , dow , doy ) ;
if ( nextW >= 1 ) {
return Math . min ( w , nextW ) ;
}
return w ;
}
function weekOfGivenYear ( marker , year , dow , doy ) {
var firstWeekStart = arrayToUtcDate ( [ year , 0 , 1 + firstWeekOffset ( year , dow , doy ) ] ) ;
var dayStart = startOfDay ( marker ) ;
var days = Math . round ( diffDays ( firstWeekStart , dayStart ) ) ;
return Math . floor ( days / 7 ) + 1 ; // zero-indexed
}
// start-of-first-week - start-of-year
function firstWeekOffset ( year , dow , doy ) {
// first-week day -- which january is always in the first week (4 for iso, 1 for other)
var fwd = 7 + dow - doy ;
// first-week day local weekday -- which local weekday is fwd
var fwdlw = ( 7 + arrayToUtcDate ( [ year , 0 , fwd ] ) . getUTCDay ( ) - dow ) % 7 ;
return - fwdlw + fwd - 1 ;
}
// Array Conversion
function dateToLocalArray ( date ) {
return [
date . getFullYear ( ) ,
date . getMonth ( ) ,
date . getDate ( ) ,
date . getHours ( ) ,
date . getMinutes ( ) ,
date . getSeconds ( ) ,
date . getMilliseconds ( )
] ;
}
function arrayToLocalDate ( a ) {
return new Date ( a [ 0 ] , a [ 1 ] || 0 , a [ 2 ] == null ? 1 : a [ 2 ] , // day of month
a [ 3 ] || 0 , a [ 4 ] || 0 , a [ 5 ] || 0 ) ;
}
function dateToUtcArray ( date ) {
return [
date . getUTCFullYear ( ) ,
date . getUTCMonth ( ) ,
date . getUTCDate ( ) ,
date . getUTCHours ( ) ,
date . getUTCMinutes ( ) ,
date . getUTCSeconds ( ) ,
date . getUTCMilliseconds ( )
] ;
}
function arrayToUtcDate ( a ) {
// according to web standards (and Safari), a month index is required.
// massage if only given a year.
if ( a . length === 1 ) {
a = a . concat ( [ 0 ] ) ;
}
return new Date ( Date . UTC . apply ( Date , a ) ) ;
}
// Other Utils
function isValidDate ( m ) {
return ! isNaN ( m . valueOf ( ) ) ;
}
function timeAsMs ( m ) {
return m . getUTCHours ( ) * 1000 * 60 * 60 +
m . getUTCMinutes ( ) * 1000 * 60 +
m . getUTCSeconds ( ) * 1000 +
m . getUTCMilliseconds ( ) ;
}
var INTERNAL _UNITS = [ 'years' , 'months' , 'days' , 'milliseconds' ] ;
var PARSE _RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/ ;
// Parsing and Creation
function createDuration ( input , unit ) {
var _a ;
if ( typeof input === 'string' ) {
return parseString ( input ) ;
}
else if ( typeof input === 'object' && input ) { // non-null object
return normalizeObject ( input ) ;
}
else if ( typeof input === 'number' ) {
return normalizeObject ( ( _a = { } , _a [ unit || 'milliseconds' ] = input , _a ) ) ;
}
else {
return null ;
}
}
function parseString ( s ) {
var m = PARSE _RE . exec ( s ) ;
if ( m ) {
var sign = m [ 1 ] ? - 1 : 1 ;
return {
years : 0 ,
months : 0 ,
days : sign * ( m [ 2 ] ? parseInt ( m [ 2 ] , 10 ) : 0 ) ,
milliseconds : sign * ( ( m [ 3 ] ? parseInt ( m [ 3 ] , 10 ) : 0 ) * 60 * 60 * 1000 + // hours
( m [ 4 ] ? parseInt ( m [ 4 ] , 10 ) : 0 ) * 60 * 1000 + // minutes
( m [ 5 ] ? parseInt ( m [ 5 ] , 10 ) : 0 ) * 1000 + // seconds
( m [ 6 ] ? parseInt ( m [ 6 ] , 10 ) : 0 ) // ms
)
} ;
}
return null ;
}
function normalizeObject ( obj ) {
return {
years : obj . years || obj . year || 0 ,
months : obj . months || obj . month || 0 ,
days : ( obj . days || obj . day || 0 ) +
getWeeksFromInput ( obj ) * 7 ,
milliseconds : ( obj . hours || obj . hour || 0 ) * 60 * 60 * 1000 + // hours
( obj . minutes || obj . minute || 0 ) * 60 * 1000 + // minutes
( obj . seconds || obj . second || 0 ) * 1000 + // seconds
( obj . milliseconds || obj . millisecond || obj . ms || 0 ) // ms
} ;
}
function getWeeksFromInput ( obj ) {
return obj . weeks || obj . week || 0 ;
}
// Equality
function durationsEqual ( d0 , d1 ) {
return d0 . years === d1 . years &&
d0 . months === d1 . months &&
d0 . days === d1 . days &&
d0 . milliseconds === d1 . milliseconds ;
}
function isSingleDay ( dur ) {
return dur . years === 0 && dur . months === 0 && dur . days === 1 && dur . milliseconds === 0 ;
}
// Simple Math
function addDurations ( d0 , d1 ) {
return {
years : d0 . years + d1 . years ,
months : d0 . months + d1 . months ,
days : d0 . days + d1 . days ,
milliseconds : d0 . milliseconds + d1 . milliseconds
} ;
}
function subtractDurations ( d1 , d0 ) {
return {
years : d1 . years - d0 . years ,
months : d1 . months - d0 . months ,
days : d1 . days - d0 . days ,
milliseconds : d1 . milliseconds - d0 . milliseconds
} ;
}
function multiplyDuration ( d , n ) {
return {
years : d . years * n ,
months : d . months * n ,
days : d . days * n ,
milliseconds : d . milliseconds * n
} ;
}
// Conversions
// "Rough" because they are based on average-case Gregorian months/years
function asRoughYears ( dur ) {
return asRoughDays ( dur ) / 365 ;
}
function asRoughMonths ( dur ) {
return asRoughDays ( dur ) / 30 ;
}
function asRoughDays ( dur ) {
return asRoughMs ( dur ) / 864e5 ;
}
function asRoughMinutes ( dur ) {
return asRoughMs ( dur ) / ( 1000 * 60 ) ;
}
function asRoughSeconds ( dur ) {
return asRoughMs ( dur ) / 1000 ;
}
function asRoughMs ( dur ) {
return dur . years * ( 365 * 864e5 ) +
dur . months * ( 30 * 864e5 ) +
dur . days * 864e5 +
dur . milliseconds ;
}
// Advanced Math
function wholeDivideDurations ( numerator , denominator ) {
var res = null ;
for ( var i = 0 ; i < INTERNAL _UNITS . length ; i ++ ) {
var unit = INTERNAL _UNITS [ i ] ;
if ( denominator [ unit ] ) {
var localRes = numerator [ unit ] / denominator [ unit ] ;
if ( ! isInt ( localRes ) || ( res !== null && res !== localRes ) ) {
return null ;
}
res = localRes ;
}
else if ( numerator [ unit ] ) {
// needs to divide by something but can't!
return null ;
}
}
return res ;
}
function greatestDurationDenominator ( dur , dontReturnWeeks ) {
var ms = dur . milliseconds ;
if ( ms ) {
if ( ms % 1000 !== 0 ) {
return { unit : 'millisecond' , value : ms } ;
}
if ( ms % ( 1000 * 60 ) !== 0 ) {
return { unit : 'second' , value : ms / 1000 } ;
}
if ( ms % ( 1000 * 60 * 60 ) !== 0 ) {
return { unit : 'minute' , value : ms / ( 1000 * 60 ) } ;
}
if ( ms ) {
return { unit : 'hour' , value : ms / ( 1000 * 60 * 60 ) } ;
}
}
if ( dur . days ) {
if ( ! dontReturnWeeks && dur . days % 7 === 0 ) {
return { unit : 'week' , value : dur . days / 7 } ;
}
return { unit : 'day' , value : dur . days } ;
}
if ( dur . months ) {
return { unit : 'month' , value : dur . months } ;
}
if ( dur . years ) {
return { unit : 'year' , value : dur . years } ;
}
return { unit : 'millisecond' , value : 0 } ;
}
/ * F u l l C a l e n d a r - s p e c i f i c D O M U t i l i t i e s
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left
// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that.
function compensateScroll ( rowEl , scrollbarWidths ) {
if ( scrollbarWidths . left ) {
applyStyle ( rowEl , {
borderLeftWidth : 1 ,
marginLeft : scrollbarWidths . left - 1
} ) ;
}
if ( scrollbarWidths . right ) {
applyStyle ( rowEl , {
borderRightWidth : 1 ,
marginRight : scrollbarWidths . right - 1
} ) ;
}
}
// Undoes compensateScroll and restores all borders/margins
function uncompensateScroll ( rowEl ) {
applyStyle ( rowEl , {
marginLeft : '' ,
marginRight : '' ,
borderLeftWidth : '' ,
borderRightWidth : ''
} ) ;
}
// Make the mouse cursor express that an event is not allowed in the current area
function disableCursor ( ) {
document . body . classList . add ( 'fc-not-allowed' ) ;
}
// Returns the mouse cursor to its original look
function enableCursor ( ) {
document . body . classList . remove ( 'fc-not-allowed' ) ;
}
// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate.
// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering
// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and
// reduces the available height.
function distributeHeight ( els , availableHeight , shouldRedistribute ) {
// *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions,
// and it is better to be shorter than taller, to avoid creating unnecessary scrollbars.
var minOffset1 = Math . floor ( availableHeight / els . length ) ; // for non-last element
var minOffset2 = Math . floor ( availableHeight - minOffset1 * ( els . length - 1 ) ) ; // for last element *FLOORING NOTE*
var flexEls = [ ] ; // elements that are allowed to expand. array of DOM nodes
var flexOffsets = [ ] ; // amount of vertical space it takes up
var flexHeights = [ ] ; // actual css height
var usedHeight = 0 ;
undistributeHeight ( els ) ; // give all elements their natural height
// find elements that are below the recommended height (expandable).
// important to query for heights in a single first pass (to avoid reflow oscillation).
els . forEach ( function ( el , i ) {
var minOffset = i === els . length - 1 ? minOffset2 : minOffset1 ;
var naturalHeight = el . getBoundingClientRect ( ) . height ;
var naturalOffset = naturalHeight + computeVMargins ( el ) ;
if ( naturalOffset < minOffset ) {
flexEls . push ( el ) ;
flexOffsets . push ( naturalOffset ) ;
flexHeights . push ( naturalHeight ) ;
}
else {
// this element stretches past recommended height (non-expandable). mark the space as occupied.
usedHeight += naturalOffset ;
}
} ) ;
// readjust the recommended height to only consider the height available to non-maxed-out rows.
if ( shouldRedistribute ) {
availableHeight -= usedHeight ;
minOffset1 = Math . floor ( availableHeight / flexEls . length ) ;
minOffset2 = Math . floor ( availableHeight - minOffset1 * ( flexEls . length - 1 ) ) ; // *FLOORING NOTE*
}
// assign heights to all expandable elements
flexEls . forEach ( function ( el , i ) {
var minOffset = i === flexEls . length - 1 ? minOffset2 : minOffset1 ;
var naturalOffset = flexOffsets [ i ] ;
var naturalHeight = flexHeights [ i ] ;
var newHeight = minOffset - ( naturalOffset - naturalHeight ) ; // subtract the margin/padding
if ( naturalOffset < minOffset ) { // we check this again because redistribution might have changed things
el . style . height = newHeight + 'px' ;
}
} ) ;
}
// Undoes distrubuteHeight, restoring all els to their natural height
function undistributeHeight ( els ) {
els . forEach ( function ( el ) {
el . style . height = '' ;
} ) ;
}
// Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the
// cells to be that width.
// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline
function matchCellWidths ( els ) {
var maxInnerWidth = 0 ;
els . forEach ( function ( el ) {
var innerEl = el . firstChild ; // hopefully an element
if ( innerEl instanceof HTMLElement ) {
var innerWidth _1 = innerEl . getBoundingClientRect ( ) . width ;
if ( innerWidth _1 > maxInnerWidth ) {
maxInnerWidth = innerWidth _1 ;
}
}
} ) ;
maxInnerWidth ++ ; // sometimes not accurate of width the text needs to stay on one line. insurance
els . forEach ( function ( el ) {
el . style . width = maxInnerWidth + 'px' ;
} ) ;
return maxInnerWidth ;
}
// Given one element that resides inside another,
// Subtracts the height of the inner element from the outer element.
function subtractInnerElHeight ( outerEl , innerEl ) {
// effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
var reflowStyleProps = {
position : 'relative' ,
left : - 1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
} ;
applyStyle ( outerEl , reflowStyleProps ) ;
applyStyle ( innerEl , reflowStyleProps ) ;
var diff = // grab the dimensions
outerEl . getBoundingClientRect ( ) . height -
innerEl . getBoundingClientRect ( ) . height ;
// undo hack
var resetStyleProps = { position : '' , left : '' } ;
applyStyle ( outerEl , resetStyleProps ) ;
applyStyle ( innerEl , resetStyleProps ) ;
return diff ;
}
/ * S e l e c t i o n
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
function preventSelection ( el ) {
el . classList . add ( 'fc-unselectable' ) ;
el . addEventListener ( 'selectstart' , preventDefault ) ;
}
function allowSelection ( el ) {
el . classList . remove ( 'fc-unselectable' ) ;
el . removeEventListener ( 'selectstart' , preventDefault ) ;
}
/ * C o n t e x t M e n u
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
function preventContextMenu ( el ) {
el . addEventListener ( 'contextmenu' , preventDefault ) ;
}
function allowContextMenu ( el ) {
el . removeEventListener ( 'contextmenu' , preventDefault ) ;
}
/ * O b j e c t O r d e r i n g b y F i e l d
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
function parseFieldSpecs ( input ) {
var specs = [ ] ;
var tokens = [ ] ;
var i ;
var token ;
if ( typeof input === 'string' ) {
tokens = input . split ( /\s*,\s*/ ) ;
}
else if ( typeof input === 'function' ) {
tokens = [ input ] ;
}
else if ( Array . isArray ( input ) ) {
tokens = input ;
}
for ( i = 0 ; i < tokens . length ; i ++ ) {
token = tokens [ i ] ;
if ( typeof token === 'string' ) {
specs . push ( token . charAt ( 0 ) === '-' ?
{ field : token . substring ( 1 ) , order : - 1 } :
{ field : token , order : 1 } ) ;
}
else if ( typeof token === 'function' ) {
specs . push ( { func : token } ) ;
}
}
return specs ;
}
function compareByFieldSpecs ( obj0 , obj1 , fieldSpecs ) {
var i ;
var cmp ;
for ( i = 0 ; i < fieldSpecs . length ; i ++ ) {
cmp = compareByFieldSpec ( obj0 , obj1 , fieldSpecs [ i ] ) ;
if ( cmp ) {
return cmp ;
}
}
return 0 ;
}
function compareByFieldSpec ( obj0 , obj1 , fieldSpec ) {
if ( fieldSpec . func ) {
return fieldSpec . func ( obj0 , obj1 ) ;
}
return flexibleCompare ( obj0 [ fieldSpec . field ] , obj1 [ fieldSpec . field ] )
* ( fieldSpec . order || 1 ) ;
}
function flexibleCompare ( a , b ) {
if ( ! a && ! b ) {
return 0 ;
}
if ( b == null ) {
return - 1 ;
}
if ( a == null ) {
return 1 ;
}
if ( typeof a === 'string' || typeof b === 'string' ) {
return String ( a ) . localeCompare ( String ( b ) ) ;
}
return a - b ;
}
/ * S t r i n g U t i l i t i e s
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
function capitaliseFirstLetter ( str ) {
return str . charAt ( 0 ) . toUpperCase ( ) + str . slice ( 1 ) ;
}
function padStart ( val , len ) {
var s = String ( val ) ;
return '000' . substr ( 0 , len - s . length ) + s ;
}
/ * N u m b e r U t i l i t i e s
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
function compareNumbers ( a , b ) {
return a - b ;
}
function isInt ( n ) {
return n % 1 === 0 ;
}
/ * W e i r d U t i l i t i e s
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
function applyAll ( functions , thisObj , args ) {
if ( typeof functions === 'function' ) { // supplied a single function
functions = [ functions ] ;
}
if ( functions ) {
var i = void 0 ;
var ret = void 0 ;
for ( i = 0 ; i < functions . length ; i ++ ) {
ret = functions [ i ] . apply ( thisObj , args ) || ret ;
}
return ret ;
}
}
function firstDefined ( ) {
var args = [ ] ;
for ( var _i = 0 ; _i < arguments . length ; _i ++ ) {
args [ _i ] = arguments [ _i ] ;
}
for ( var i = 0 ; i < args . length ; i ++ ) {
if ( args [ i ] !== undefined ) {
return args [ i ] ;
}
}
}
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714
function debounce ( func , wait ) {
var timeout ;
var args ;
var context ;
var timestamp ;
var result ;
var later = function ( ) {
var last = new Date ( ) . valueOf ( ) - timestamp ;
if ( last < wait ) {
timeout = setTimeout ( later , wait - last ) ;
}
else {
timeout = null ;
result = func . apply ( context , args ) ;
context = args = null ;
}
} ;
return function ( ) {
context = this ;
args = arguments ;
timestamp = new Date ( ) . valueOf ( ) ;
if ( ! timeout ) {
timeout = setTimeout ( later , wait ) ;
}
return result ;
} ;
}
// Number and Boolean are only types that defaults or not computed for
// TODO: write more comments
function refineProps ( rawProps , processors , defaults , leftoverProps ) {
if ( defaults === void 0 ) { defaults = { } ; }
var refined = { } ;
for ( var key in processors ) {
var processor = processors [ key ] ;
if ( rawProps [ key ] !== undefined ) {
// found
if ( processor === Function ) {
refined [ key ] = typeof rawProps [ key ] === 'function' ? rawProps [ key ] : null ;
}
else if ( processor ) { // a refining function?
refined [ key ] = processor ( rawProps [ key ] ) ;
}
else {
refined [ key ] = rawProps [ key ] ;
}
}
else if ( defaults [ key ] !== undefined ) {
// there's an explicit default
refined [ key ] = defaults [ key ] ;
}
else {
// must compute a default
if ( processor === String ) {
refined [ key ] = '' ; // empty string is default for String
}
else if ( ! processor || processor === Number || processor === Boolean || processor === Function ) {
refined [ key ] = null ; // assign null for other non-custom processor funcs
}
else {
refined [ key ] = processor ( null ) ; // run the custom processor func
}
}
}
if ( leftoverProps ) {
for ( var key in rawProps ) {
if ( processors [ key ] === undefined ) {
leftoverProps [ key ] = rawProps [ key ] ;
}
}
}
return refined ;
}
/ * D a t e s t u f f t h a t d o e s n ' t b e l o n g i n d a t e l i b c o r e
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
// given a timed range, computes an all-day range that has the same exact duration,
// but whose start time is aligned with the start of the day.
function computeAlignedDayRange ( timedRange ) {
var dayCnt = Math . floor ( diffDays ( timedRange . start , timedRange . end ) ) || 1 ;
var start = startOfDay ( timedRange . start ) ;
var end = addDays ( start , dayCnt ) ;
return { start : start , end : end } ;
}
// given a timed range, computes an all-day range based on how for the end date bleeds into the next day
// TODO: give nextDayThreshold a default arg
function computeVisibleDayRange ( timedRange , nextDayThreshold ) {
if ( nextDayThreshold === void 0 ) { nextDayThreshold = createDuration ( 0 ) ; }
var startDay = null ;
var endDay = null ;
if ( timedRange . end ) {
endDay = startOfDay ( timedRange . end ) ;
var endTimeMS = timedRange . end . valueOf ( ) - endDay . valueOf ( ) ; // # of milliseconds into `endDay`
// If the end time is actually inclusively part of the next day and is equal to or
// beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
// Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
if ( endTimeMS && endTimeMS >= asRoughMs ( nextDayThreshold ) ) {
endDay = addDays ( endDay , 1 ) ;
}
}
if ( timedRange . start ) {
startDay = startOfDay ( timedRange . start ) ; // the beginning of the day the range starts
// If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
if ( endDay && endDay <= startDay ) {
endDay = addDays ( startDay , 1 ) ;
}
}
return { start : startDay , end : endDay } ;
}
// spans from one day into another?
function isMultiDayRange ( range ) {
var visibleRange = computeVisibleDayRange ( range ) ;
return diffDays ( visibleRange . start , visibleRange . end ) > 1 ;
}
function diffDates ( date0 , date1 , dateEnv , largeUnit ) {
if ( largeUnit === 'year' ) {
return createDuration ( dateEnv . diffWholeYears ( date0 , date1 ) , 'year' ) ;
}
else if ( largeUnit === 'month' ) {
return createDuration ( dateEnv . diffWholeMonths ( date0 , date1 ) , 'month' ) ;
}
else {
return diffDayAndTime ( date0 , date1 ) ; // returns a duration
}
}
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2020-06-01 11:05:25 +00:00
Copyright ( c ) Microsoft Corporation .
2019-08-28 10:59:33 +00:00
2020-06-01 11:05:25 +00:00
Permission to use , copy , modify , and / or distribute this software for any
purpose with or without fee is hereby granted .
2019-08-28 10:59:33 +00:00
2020-06-01 11:05:25 +00:00
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS . IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL , DIRECT ,
INDIRECT , OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE , DATA OR PROFITS , WHETHER IN AN ACTION OF CONTRACT , NEGLIGENCE OR
OTHER TORTIOUS ACTION , ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE .
2019-08-28 10:59:33 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/* global Reflect, Promise */
var extendStatics = function ( d , b ) {
extendStatics = Object . setPrototypeOf ||
( { _ _proto _ _ : [ ] } instanceof Array && function ( d , b ) { d . _ _proto _ _ = b ; } ) ||
function ( d , b ) { for ( var p in b ) if ( b . hasOwnProperty ( p ) ) d [ p ] = b [ p ] ; } ;
return extendStatics ( d , b ) ;
} ;
function _ _extends ( d , b ) {
extendStatics ( d , b ) ;
function _ _ ( ) { this . constructor = d ; }
d . prototype = b === null ? Object . create ( b ) : ( _ _ . prototype = b . prototype , new _ _ ( ) ) ;
}
var _ _assign = function ( ) {
_ _assign = Object . assign || function _ _assign ( t ) {
for ( var s , i = 1 , n = arguments . length ; i < n ; i ++ ) {
s = arguments [ i ] ;
for ( var p in s ) if ( Object . prototype . hasOwnProperty . call ( s , p ) ) t [ p ] = s [ p ] ;
}
return t ;
} ;
return _ _assign . apply ( this , arguments ) ;
} ;
function parseRecurring ( eventInput , allDayDefault , dateEnv , recurringTypes , leftovers ) {
for ( var i = 0 ; i < recurringTypes . length ; i ++ ) {
var localLeftovers = { } ;
var parsed = recurringTypes [ i ] . parse ( eventInput , localLeftovers , dateEnv ) ;
if ( parsed ) {
var allDay = localLeftovers . allDay ;
delete localLeftovers . allDay ; // remove from leftovers
if ( allDay == null ) {
allDay = allDayDefault ;
if ( allDay == null ) {
allDay = parsed . allDayGuess ;
if ( allDay == null ) {
allDay = false ;
}
}
}
_ _assign ( leftovers , localLeftovers ) ;
return {
allDay : allDay ,
duration : parsed . duration ,
typeData : parsed . typeData ,
typeId : i
} ;
}
}
return null ;
}
/ *
Event MUST have a recurringDef
* /
function expandRecurringRanges ( eventDef , duration , framingRange , dateEnv , recurringTypes ) {
var typeDef = recurringTypes [ eventDef . recurringDef . typeId ] ;
var markers = typeDef . expand ( eventDef . recurringDef . typeData , {
start : dateEnv . subtract ( framingRange . start , duration ) ,
end : framingRange . end
} , dateEnv ) ;
// the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
if ( eventDef . allDay ) {
markers = markers . map ( startOfDay ) ;
}
return markers ;
}
var hasOwnProperty = Object . prototype . hasOwnProperty ;
// 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.
function mergeProps ( propObjs , complexProps ) {
var dest = { } ;
var i ;
var name ;
var complexObjs ;
var j ;
var val ;
var props ;
if ( complexProps ) {
for ( i = 0 ; i < complexProps . length ; i ++ ) {
name = complexProps [ i ] ;
complexObjs = [ ] ;
// collect the trailing object values, stopping when a non-object is discovered
for ( j = propObjs . length - 1 ; j >= 0 ; j -- ) {
val = propObjs [ j ] [ name ] ;
if ( typeof val === 'object' && val ) { // non-null object
complexObjs . unshift ( val ) ;
}
else if ( val !== undefined ) {
dest [ name ] = val ; // if there were no objects, this value will be used
break ;
}
}
// if the trailing values were objects, use the merged value
if ( complexObjs . length ) {
dest [ name ] = mergeProps ( complexObjs ) ;
}
}
}
// copy values into the destination, going from last to first
for ( i = propObjs . length - 1 ; i >= 0 ; i -- ) {
props = propObjs [ i ] ;
for ( name in props ) {
if ( ! ( name in dest ) ) { // if already assigned by previous props or complex props, don't reassign
dest [ name ] = props [ name ] ;
}
}
}
return dest ;
}
function filterHash ( hash , func ) {
var filtered = { } ;
for ( var key in hash ) {
if ( func ( hash [ key ] , key ) ) {
filtered [ key ] = hash [ key ] ;
}
}
return filtered ;
}
function mapHash ( hash , func ) {
var newHash = { } ;
for ( var key in hash ) {
newHash [ key ] = func ( hash [ key ] , key ) ;
}
return newHash ;
}
function arrayToHash ( a ) {
var hash = { } ;
for ( var _i = 0 , a _1 = a ; _i < a _1 . length ; _i ++ ) {
var item = a _1 [ _i ] ;
hash [ item ] = true ;
}
return hash ;
}
function hashValuesToArray ( obj ) {
var a = [ ] ;
for ( var key in obj ) {
a . push ( obj [ key ] ) ;
}
return a ;
}
function isPropsEqual ( obj0 , obj1 ) {
for ( var key in obj0 ) {
if ( hasOwnProperty . call ( obj0 , key ) ) {
if ( ! ( key in obj1 ) ) {
return false ;
}
}
}
for ( var key in obj1 ) {
if ( hasOwnProperty . call ( obj1 , key ) ) {
if ( obj0 [ key ] !== obj1 [ key ] ) {
return false ;
}
}
}
return true ;
}
function parseEvents ( rawEvents , sourceId , calendar , allowOpenRange ) {
var eventStore = createEmptyEventStore ( ) ;
for ( var _i = 0 , rawEvents _1 = rawEvents ; _i < rawEvents _1 . length ; _i ++ ) {
var rawEvent = rawEvents _1 [ _i ] ;
var tuple = parseEvent ( rawEvent , sourceId , calendar , allowOpenRange ) ;
if ( tuple ) {
eventTupleToStore ( tuple , eventStore ) ;
}
}
return eventStore ;
}
function eventTupleToStore ( tuple , eventStore ) {
if ( eventStore === void 0 ) { eventStore = createEmptyEventStore ( ) ; }
eventStore . defs [ tuple . def . defId ] = tuple . def ;
if ( tuple . instance ) {
eventStore . instances [ tuple . instance . instanceId ] = tuple . instance ;
}
return eventStore ;
}
function expandRecurring ( eventStore , framingRange , calendar ) {
var dateEnv = calendar . dateEnv ;
var defs = eventStore . defs , instances = eventStore . instances ;
// remove existing recurring instances
instances = filterHash ( instances , function ( instance ) {
return ! defs [ instance . defId ] . recurringDef ;
} ) ;
for ( var defId in defs ) {
var def = defs [ defId ] ;
if ( def . recurringDef ) {
var duration = def . recurringDef . duration ;
if ( ! duration ) {
duration = def . allDay ?
calendar . defaultAllDayEventDuration :
calendar . defaultTimedEventDuration ;
}
var starts = expandRecurringRanges ( def , duration , framingRange , calendar . dateEnv , calendar . pluginSystem . hooks . recurringTypes ) ;
for ( var _i = 0 , starts _1 = starts ; _i < starts _1 . length ; _i ++ ) {
var start = starts _1 [ _i ] ;
var instance = createEventInstance ( defId , {
start : start ,
end : dateEnv . add ( start , duration )
} ) ;
instances [ instance . instanceId ] = instance ;
}
}
}
return { defs : defs , instances : instances } ;
}
// retrieves events that have the same groupId as the instance specified by `instanceId`
// or they are the same as the instance.
// why might instanceId not be in the store? an event from another calendar?
function getRelevantEvents ( eventStore , instanceId ) {
var instance = eventStore . instances [ instanceId ] ;
if ( instance ) {
var def _1 = eventStore . defs [ instance . defId ] ;
// get events/instances with same group
var newStore = filterEventStoreDefs ( eventStore , function ( lookDef ) {
return isEventDefsGrouped ( def _1 , lookDef ) ;
} ) ;
// add the original
// TODO: wish we could use eventTupleToStore or something like it
newStore . defs [ def _1 . defId ] = def _1 ;
newStore . instances [ instance . instanceId ] = instance ;
return newStore ;
}
return createEmptyEventStore ( ) ;
}
function isEventDefsGrouped ( def0 , def1 ) {
return Boolean ( def0 . groupId && def0 . groupId === def1 . groupId ) ;
}
function transformRawEvents ( rawEvents , eventSource , calendar ) {
var calEachTransform = calendar . opt ( 'eventDataTransform' ) ;
var sourceEachTransform = eventSource ? eventSource . eventDataTransform : null ;
if ( sourceEachTransform ) {
rawEvents = transformEachRawEvent ( rawEvents , sourceEachTransform ) ;
}
if ( calEachTransform ) {
rawEvents = transformEachRawEvent ( rawEvents , calEachTransform ) ;
}
return rawEvents ;
}
function transformEachRawEvent ( rawEvents , func ) {
var refinedEvents ;
if ( ! func ) {
refinedEvents = rawEvents ;
}
else {
refinedEvents = [ ] ;
for ( var _i = 0 , rawEvents _2 = rawEvents ; _i < rawEvents _2 . length ; _i ++ ) {
var rawEvent = rawEvents _2 [ _i ] ;
var refinedEvent = func ( rawEvent ) ;
if ( refinedEvent ) {
refinedEvents . push ( refinedEvent ) ;
}
else if ( refinedEvent == null ) {
refinedEvents . push ( rawEvent ) ;
} // if a different falsy value, do nothing
}
}
return refinedEvents ;
}
function createEmptyEventStore ( ) {
return { defs : { } , instances : { } } ;
}
function mergeEventStores ( store0 , store1 ) {
return {
defs : _ _assign ( { } , store0 . defs , store1 . defs ) ,
instances : _ _assign ( { } , store0 . instances , store1 . instances )
} ;
}
function filterEventStoreDefs ( eventStore , filterFunc ) {
var defs = filterHash ( eventStore . defs , filterFunc ) ;
var instances = filterHash ( eventStore . instances , function ( instance ) {
return defs [ instance . defId ] ; // still exists?
} ) ;
return { defs : defs , instances : instances } ;
}
function parseRange ( input , dateEnv ) {
var start = null ;
var end = null ;
if ( input . start ) {
start = dateEnv . createMarker ( input . start ) ;
}
if ( input . end ) {
end = dateEnv . createMarker ( input . end ) ;
}
if ( ! start && ! end ) {
return null ;
}
if ( start && end && end < start ) {
return null ;
}
return { start : start , end : end } ;
}
// SIDE-EFFECT: will mutate ranges.
// Will return a new array result.
function invertRanges ( ranges , constraintRange ) {
var invertedRanges = [ ] ;
var start = constraintRange . start ; // the end of the previous range. the start of the new range
var i ;
var dateRange ;
// ranges need to be in order. required for our date-walking algorithm
ranges . sort ( compareRanges ) ;
for ( i = 0 ; i < ranges . length ; i ++ ) {
dateRange = ranges [ i ] ;
// add the span of time before the event (if there is any)
if ( dateRange . start > start ) { // compare millisecond time (skip any ambig logic)
invertedRanges . push ( { start : start , end : dateRange . start } ) ;
}
if ( dateRange . end > start ) {
start = dateRange . end ;
}
}
// add the span of time after the last event (if there is any)
if ( start < constraintRange . end ) { // compare millisecond time (skip any ambig logic)
invertedRanges . push ( { start : start , end : constraintRange . end } ) ;
}
return invertedRanges ;
}
function compareRanges ( range0 , range1 ) {
return range0 . start . valueOf ( ) - range1 . start . valueOf ( ) ; // earlier ranges go first
}
function intersectRanges ( range0 , range1 ) {
var start = range0 . start ;
var end = range0 . end ;
var newRange = null ;
if ( range1 . start !== null ) {
if ( start === null ) {
start = range1 . start ;
}
else {
start = new Date ( Math . max ( start . valueOf ( ) , range1 . start . valueOf ( ) ) ) ;
}
}
if ( range1 . end != null ) {
if ( end === null ) {
end = range1 . end ;
}
else {
end = new Date ( Math . min ( end . valueOf ( ) , range1 . end . valueOf ( ) ) ) ;
}
}
if ( start === null || end === null || start < end ) {
newRange = { start : start , end : end } ;
}
return newRange ;
}
function rangesEqual ( range0 , range1 ) {
return ( range0 . start === null ? null : range0 . start . valueOf ( ) ) === ( range1 . start === null ? null : range1 . start . valueOf ( ) ) &&
( range0 . end === null ? null : range0 . end . valueOf ( ) ) === ( range1 . end === null ? null : range1 . end . valueOf ( ) ) ;
}
function rangesIntersect ( range0 , range1 ) {
return ( range0 . end === null || range1 . start === null || range0 . end > range1 . start ) &&
( range0 . start === null || range1 . end === null || range0 . start < range1 . end ) ;
}
function rangeContainsRange ( outerRange , innerRange ) {
return ( outerRange . start === null || ( innerRange . start !== null && innerRange . start >= outerRange . start ) ) &&
( outerRange . end === null || ( innerRange . end !== null && innerRange . end <= outerRange . end ) ) ;
}
function rangeContainsMarker ( range , date ) {
return ( range . start === null || date >= range . start ) &&
( range . end === null || date < range . end ) ;
}
// If the given date is not within the given range, move it inside.
// (If it's past the end, make it one millisecond before the end).
function constrainMarkerToRange ( date , range ) {
if ( range . start != null && date < range . start ) {
return range . start ;
}
if ( range . end != null && date >= range . end ) {
return new Date ( range . end . valueOf ( ) - 1 ) ;
}
return date ;
}
function removeExact ( array , exactVal ) {
var removeCnt = 0 ;
var i = 0 ;
while ( i < array . length ) {
if ( array [ i ] === exactVal ) {
array . splice ( i , 1 ) ;
removeCnt ++ ;
}
else {
i ++ ;
}
}
return removeCnt ;
}
function isArraysEqual ( a0 , a1 ) {
var len = a0 . length ;
var i ;
if ( len !== a1 . length ) { // not array? or not same length?
return false ;
}
for ( i = 0 ; i < len ; i ++ ) {
if ( a0 [ i ] !== a1 [ i ] ) {
return false ;
}
}
return true ;
}
function memoize ( workerFunc ) {
var args ;
var res ;
return function ( ) {
if ( ! args || ! isArraysEqual ( args , arguments ) ) {
args = arguments ;
res = workerFunc . apply ( this , arguments ) ;
}
return res ;
} ;
}
/ *
always executes the workerFunc , but if the result is equal to the previous result ,
return the previous result instead .
* /
function memoizeOutput ( workerFunc , equalityFunc ) {
var cachedRes = null ;
return function ( ) {
var newRes = workerFunc . apply ( this , arguments ) ;
if ( cachedRes === null || ! ( cachedRes === newRes || equalityFunc ( cachedRes , newRes ) ) ) {
cachedRes = newRes ;
}
return cachedRes ;
} ;
}
var EXTENDED _SETTINGS _AND _SEVERITIES = {
week : 3 ,
separator : 0 ,
omitZeroMinute : 0 ,
meridiem : 0 ,
omitCommas : 0
} ;
var STANDARD _DATE _PROP _SEVERITIES = {
timeZoneName : 7 ,
era : 6 ,
year : 5 ,
month : 4 ,
day : 2 ,
weekday : 2 ,
hour : 1 ,
minute : 1 ,
second : 1
} ;
var MERIDIEM _RE = /\s*([ap])\.?m\.?/i ; // eats up leading spaces too
var COMMA _RE = /,/g ; // we need re for globalness
var MULTI _SPACE _RE = /\s+/g ;
var LTR _RE = /\u200e/g ; // control character
var UTC _RE = /UTC|GMT/ ;
var NativeFormatter = /** @class */ ( function ( ) {
function NativeFormatter ( formatSettings ) {
var standardDateProps = { } ;
var extendedSettings = { } ;
var severity = 0 ;
for ( var name _1 in formatSettings ) {
if ( name _1 in EXTENDED _SETTINGS _AND _SEVERITIES ) {
extendedSettings [ name _1 ] = formatSettings [ name _1 ] ;
severity = Math . max ( EXTENDED _SETTINGS _AND _SEVERITIES [ name _1 ] , severity ) ;
}
else {
standardDateProps [ name _1 ] = formatSettings [ name _1 ] ;
if ( name _1 in STANDARD _DATE _PROP _SEVERITIES ) {
severity = Math . max ( STANDARD _DATE _PROP _SEVERITIES [ name _1 ] , severity ) ;
}
}
}
this . standardDateProps = standardDateProps ;
this . extendedSettings = extendedSettings ;
this . severity = severity ;
this . buildFormattingFunc = memoize ( buildFormattingFunc ) ;
}
NativeFormatter . prototype . format = function ( date , context ) {
return this . buildFormattingFunc ( this . standardDateProps , this . extendedSettings , context ) ( date ) ;
} ;
NativeFormatter . prototype . formatRange = function ( start , end , context ) {
var _a = this , standardDateProps = _a . standardDateProps , extendedSettings = _a . extendedSettings ;
var diffSeverity = computeMarkerDiffSeverity ( start . marker , end . marker , context . calendarSystem ) ;
if ( ! diffSeverity ) {
return this . format ( start , context ) ;
}
var biggestUnitForPartial = diffSeverity ;
if ( biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
( standardDateProps . year === 'numeric' || standardDateProps . year === '2-digit' ) &&
( standardDateProps . month === 'numeric' || standardDateProps . month === '2-digit' ) &&
( standardDateProps . day === 'numeric' || standardDateProps . day === '2-digit' ) ) {
biggestUnitForPartial = 1 ; // make it look like the dates are only different in terms of time
}
var full0 = this . format ( start , context ) ;
var full1 = this . format ( end , context ) ;
if ( full0 === full1 ) {
return full0 ;
}
var partialDateProps = computePartialFormattingOptions ( standardDateProps , biggestUnitForPartial ) ;
var partialFormattingFunc = buildFormattingFunc ( partialDateProps , extendedSettings , context ) ;
var partial0 = partialFormattingFunc ( start ) ;
var partial1 = partialFormattingFunc ( end ) ;
var insertion = findCommonInsertion ( full0 , partial0 , full1 , partial1 ) ;
var separator = extendedSettings . separator || '' ;
if ( insertion ) {
return insertion . before + partial0 + separator + partial1 + insertion . after ;
}
return full0 + separator + full1 ;
} ;
NativeFormatter . prototype . getLargestUnit = function ( ) {
switch ( this . severity ) {
case 7 :
case 6 :
case 5 :
return 'year' ;
case 4 :
return 'month' ;
case 3 :
return 'week' ;
default :
return 'day' ;
}
} ;
return NativeFormatter ;
} ( ) ) ;
function buildFormattingFunc ( standardDateProps , extendedSettings , context ) {
var standardDatePropCnt = Object . keys ( standardDateProps ) . length ;
if ( standardDatePropCnt === 1 && standardDateProps . timeZoneName === 'short' ) {
return function ( date ) {
return formatTimeZoneOffset ( date . timeZoneOffset ) ;
} ;
}
if ( standardDatePropCnt === 0 && extendedSettings . week ) {
return function ( date ) {
return formatWeekNumber ( context . computeWeekNumber ( date . marker ) , context . weekLabel , context . locale , extendedSettings . week ) ;
} ;
}
return buildNativeFormattingFunc ( standardDateProps , extendedSettings , context ) ;
}
function buildNativeFormattingFunc ( standardDateProps , extendedSettings , context ) {
standardDateProps = _ _assign ( { } , standardDateProps ) ; // copy
extendedSettings = _ _assign ( { } , extendedSettings ) ; // copy
sanitizeSettings ( standardDateProps , extendedSettings ) ;
standardDateProps . timeZone = 'UTC' ; // we leverage the only guaranteed timeZone for our UTC markers
var normalFormat = new Intl . DateTimeFormat ( context . locale . codes , standardDateProps ) ;
var zeroFormat ; // needed?
if ( extendedSettings . omitZeroMinute ) {
var zeroProps = _ _assign ( { } , standardDateProps ) ;
delete zeroProps . minute ; // seconds and ms were already considered in sanitizeSettings
zeroFormat = new Intl . DateTimeFormat ( context . locale . codes , zeroProps ) ;
}
return function ( date ) {
var marker = date . marker ;
var format ;
if ( zeroFormat && ! marker . getUTCMinutes ( ) ) {
format = zeroFormat ;
}
else {
format = normalFormat ;
}
var s = format . format ( marker ) ;
return postProcess ( s , date , standardDateProps , extendedSettings , context ) ;
} ;
}
function sanitizeSettings ( standardDateProps , extendedSettings ) {
// deal with a browser inconsistency where formatting the timezone
// requires that the hour/minute be present.
if ( standardDateProps . timeZoneName ) {
if ( ! standardDateProps . hour ) {
standardDateProps . hour = '2-digit' ;
}
if ( ! standardDateProps . minute ) {
standardDateProps . minute = '2-digit' ;
}
}
// only support short timezone names
if ( standardDateProps . timeZoneName === 'long' ) {
standardDateProps . timeZoneName = 'short' ;
}
// if requesting to display seconds, MUST display minutes
if ( extendedSettings . omitZeroMinute && ( standardDateProps . second || standardDateProps . millisecond ) ) {
delete extendedSettings . omitZeroMinute ;
}
}
function postProcess ( s , date , standardDateProps , extendedSettings , context ) {
s = s . replace ( LTR _RE , '' ) ; // remove left-to-right control chars. do first. good for other regexes
if ( standardDateProps . timeZoneName === 'short' ) {
s = injectTzoStr ( s , ( context . timeZone === 'UTC' || date . timeZoneOffset == null ) ?
'UTC' : // important to normalize for IE, which does "GMT"
formatTimeZoneOffset ( date . timeZoneOffset ) ) ;
}
if ( extendedSettings . omitCommas ) {
s = s . replace ( COMMA _RE , '' ) . trim ( ) ;
}
if ( extendedSettings . omitZeroMinute ) {
s = s . replace ( ':00' , '' ) ; // zeroFormat doesn't always achieve this
}
// ^ do anything that might create adjacent spaces before this point,
// because MERIDIEM_RE likes to eat up loading spaces
if ( extendedSettings . meridiem === false ) {
s = s . replace ( MERIDIEM _RE , '' ) . trim ( ) ;
}
else if ( extendedSettings . meridiem === 'narrow' ) { // a/p
s = s . replace ( MERIDIEM _RE , function ( m0 , m1 ) {
return m1 . toLocaleLowerCase ( ) ;
} ) ;
}
else if ( extendedSettings . meridiem === 'short' ) { // am/pm
s = s . replace ( MERIDIEM _RE , function ( m0 , m1 ) {
return m1 . toLocaleLowerCase ( ) + 'm' ;
} ) ;
}
else if ( extendedSettings . meridiem === 'lowercase' ) { // other meridiem transformers already converted to lowercase
s = s . replace ( MERIDIEM _RE , function ( m0 ) {
return m0 . toLocaleLowerCase ( ) ;
} ) ;
}
s = s . replace ( MULTI _SPACE _RE , ' ' ) ;
s = s . trim ( ) ;
return s ;
}
function injectTzoStr ( s , tzoStr ) {
var replaced = false ;
s = s . replace ( UTC _RE , function ( ) {
replaced = true ;
return tzoStr ;
} ) ;
// IE11 doesn't include UTC/GMT in the original string, so append to end
if ( ! replaced ) {
s += ' ' + tzoStr ;
}
return s ;
}
function formatWeekNumber ( num , weekLabel , locale , display ) {
var parts = [ ] ;
if ( display === 'narrow' ) {
parts . push ( weekLabel ) ;
}
else if ( display === 'short' ) {
parts . push ( weekLabel , ' ' ) ;
}
// otherwise, considered 'numeric'
parts . push ( locale . simpleNumberFormat . format ( num ) ) ;
if ( locale . options . isRtl ) { // TODO: use control characters instead?
parts . reverse ( ) ;
}
return parts . join ( '' ) ;
}
// Range Formatting Utils
// 0 = exactly the same
// 1 = different by time
// and bigger
function computeMarkerDiffSeverity ( d0 , d1 , ca ) {
if ( ca . getMarkerYear ( d0 ) !== ca . getMarkerYear ( d1 ) ) {
return 5 ;
}
if ( ca . getMarkerMonth ( d0 ) !== ca . getMarkerMonth ( d1 ) ) {
return 4 ;
}
if ( ca . getMarkerDay ( d0 ) !== ca . getMarkerDay ( d1 ) ) {
return 2 ;
}
if ( timeAsMs ( d0 ) !== timeAsMs ( d1 ) ) {
return 1 ;
}
return 0 ;
}
function computePartialFormattingOptions ( options , biggestUnit ) {
var partialOptions = { } ;
for ( var name _2 in options ) {
if ( ! ( name _2 in STANDARD _DATE _PROP _SEVERITIES ) || // not a date part prop (like timeZone)
STANDARD _DATE _PROP _SEVERITIES [ name _2 ] <= biggestUnit ) {
partialOptions [ name _2 ] = options [ name _2 ] ;
}
}
return partialOptions ;
}
function findCommonInsertion ( full0 , partial0 , full1 , partial1 ) {
var i0 = 0 ;
while ( i0 < full0 . length ) {
var found0 = full0 . indexOf ( partial0 , i0 ) ;
if ( found0 === - 1 ) {
break ;
}
var before0 = full0 . substr ( 0 , found0 ) ;
i0 = found0 + partial0 . length ;
var after0 = full0 . substr ( i0 ) ;
var i1 = 0 ;
while ( i1 < full1 . length ) {
var found1 = full1 . indexOf ( partial1 , i1 ) ;
if ( found1 === - 1 ) {
break ;
}
var before1 = full1 . substr ( 0 , found1 ) ;
i1 = found1 + partial1 . length ;
var after1 = full1 . substr ( i1 ) ;
if ( before0 === before1 && after0 === after1 ) {
return {
before : before0 ,
after : after0
} ;
}
}
}
return null ;
}
/ *
TODO : fix the terminology of "formatter" vs "formatting func"
* /
/ *
At the time of instantiation , this object does not know which cmd - formatting system it will use .
It receives this at the time of formatting , as a setting .
* /
var CmdFormatter = /** @class */ ( function ( ) {
function CmdFormatter ( cmdStr , separator ) {
this . cmdStr = cmdStr ;
this . separator = separator ;
}
CmdFormatter . prototype . format = function ( date , context ) {
return context . cmdFormatter ( this . cmdStr , createVerboseFormattingArg ( date , null , context , this . separator ) ) ;
} ;
CmdFormatter . prototype . formatRange = function ( start , end , context ) {
return context . cmdFormatter ( this . cmdStr , createVerboseFormattingArg ( start , end , context , this . separator ) ) ;
} ;
return CmdFormatter ;
} ( ) ) ;
var FuncFormatter = /** @class */ ( function ( ) {
function FuncFormatter ( func ) {
this . func = func ;
}
FuncFormatter . prototype . format = function ( date , context ) {
return this . func ( createVerboseFormattingArg ( date , null , context ) ) ;
} ;
FuncFormatter . prototype . formatRange = function ( start , end , context ) {
return this . func ( createVerboseFormattingArg ( start , end , context ) ) ;
} ;
return FuncFormatter ;
} ( ) ) ;
// Formatter Object Creation
function createFormatter ( input , defaultSeparator ) {
if ( typeof input === 'object' && input ) { // non-null object
if ( typeof defaultSeparator === 'string' ) {
input = _ _assign ( { separator : defaultSeparator } , input ) ;
}
return new NativeFormatter ( input ) ;
}
else if ( typeof input === 'string' ) {
return new CmdFormatter ( input , defaultSeparator ) ;
}
else if ( typeof input === 'function' ) {
return new FuncFormatter ( input ) ;
}
}
// String Utils
// timeZoneOffset is in minutes
function buildIsoString ( marker , timeZoneOffset , stripZeroTime ) {
if ( stripZeroTime === void 0 ) { stripZeroTime = false ; }
var s = marker . toISOString ( ) ;
s = s . replace ( '.000' , '' ) ;
if ( stripZeroTime ) {
s = s . replace ( 'T00:00:00Z' , '' ) ;
}
if ( s . length > 10 ) { // time part wasn't stripped, can add timezone info
if ( timeZoneOffset == null ) {
s = s . replace ( 'Z' , '' ) ;
}
else if ( timeZoneOffset !== 0 ) {
s = s . replace ( 'Z' , formatTimeZoneOffset ( timeZoneOffset , true ) ) ;
}
// otherwise, its UTC-0 and we want to keep the Z
}
return s ;
}
function formatIsoTimeString ( marker ) {
return padStart ( marker . getUTCHours ( ) , 2 ) + ':' +
padStart ( marker . getUTCMinutes ( ) , 2 ) + ':' +
padStart ( marker . getUTCSeconds ( ) , 2 ) ;
}
function formatTimeZoneOffset ( minutes , doIso ) {
if ( doIso === void 0 ) { doIso = false ; }
var sign = minutes < 0 ? '-' : '+' ;
var abs = Math . abs ( minutes ) ;
var hours = Math . floor ( abs / 60 ) ;
var mins = Math . round ( abs % 60 ) ;
if ( doIso ) {
return sign + padStart ( hours , 2 ) + ':' + padStart ( mins , 2 ) ;
}
else {
return 'GMT' + sign + hours + ( mins ? ':' + padStart ( mins , 2 ) : '' ) ;
}
}
// Arg Utils
function createVerboseFormattingArg ( start , end , context , separator ) {
var startInfo = expandZonedMarker ( start , context . calendarSystem ) ;
var endInfo = end ? expandZonedMarker ( end , context . calendarSystem ) : null ;
return {
date : startInfo ,
start : startInfo ,
end : endInfo ,
timeZone : context . timeZone ,
localeCodes : context . locale . codes ,
separator : separator
} ;
}
function expandZonedMarker ( dateInfo , calendarSystem ) {
var a = calendarSystem . markerToArray ( dateInfo . marker ) ;
return {
marker : dateInfo . marker ,
timeZoneOffset : dateInfo . timeZoneOffset ,
array : a ,
year : a [ 0 ] ,
month : a [ 1 ] ,
day : a [ 2 ] ,
hour : a [ 3 ] ,
minute : a [ 4 ] ,
second : a [ 5 ] ,
millisecond : a [ 6 ]
} ;
}
var EventSourceApi = /** @class */ ( function ( ) {
function EventSourceApi ( calendar , internalEventSource ) {
this . calendar = calendar ;
this . internalEventSource = internalEventSource ;
}
EventSourceApi . prototype . remove = function ( ) {
this . calendar . dispatch ( {
type : 'REMOVE_EVENT_SOURCE' ,
sourceId : this . internalEventSource . sourceId
} ) ;
} ;
EventSourceApi . prototype . refetch = function ( ) {
this . calendar . dispatch ( {
type : 'FETCH_EVENT_SOURCES' ,
sourceIds : [ this . internalEventSource . sourceId ]
} ) ;
} ;
Object . defineProperty ( EventSourceApi . prototype , "id" , {
get : function ( ) {
return this . internalEventSource . publicId ;
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventSourceApi . prototype , "url" , {
// only relevant to json-feed event sources
get : function ( ) {
return this . internalEventSource . meta . url ;
} ,
enumerable : true ,
configurable : true
} ) ;
return EventSourceApi ;
} ( ) ) ;
var EventApi = /** @class */ ( function ( ) {
function EventApi ( calendar , def , instance ) {
this . _calendar = calendar ;
this . _def = def ;
this . _instance = instance || null ;
}
/ *
TODO : make event struct more responsible for this
* /
EventApi . prototype . setProp = function ( name , val ) {
var _a , _b ;
if ( name in DATE _PROPS ) ;
else if ( name in NON _DATE _PROPS ) {
if ( typeof NON _DATE _PROPS [ name ] === 'function' ) {
val = NON _DATE _PROPS [ name ] ( val ) ;
}
this . mutate ( {
standardProps : ( _a = { } , _a [ name ] = val , _a )
} ) ;
}
else if ( name in UNSCOPED _EVENT _UI _PROPS ) {
var ui = void 0 ;
if ( typeof UNSCOPED _EVENT _UI _PROPS [ name ] === 'function' ) {
val = UNSCOPED _EVENT _UI _PROPS [ name ] ( val ) ;
}
if ( name === 'color' ) {
ui = { backgroundColor : val , borderColor : val } ;
}
else if ( name === 'editable' ) {
ui = { startEditable : val , durationEditable : val } ;
}
else {
ui = ( _b = { } , _b [ name ] = val , _b ) ;
}
this . mutate ( {
standardProps : { ui : ui }
} ) ;
}
} ;
EventApi . prototype . setExtendedProp = function ( name , val ) {
var _a ;
this . mutate ( {
extendedProps : ( _a = { } , _a [ name ] = val , _a )
} ) ;
} ;
EventApi . prototype . setStart = function ( startInput , options ) {
if ( options === void 0 ) { options = { } ; }
var dateEnv = this . _calendar . dateEnv ;
var start = dateEnv . createMarker ( startInput ) ;
if ( start && this . _instance ) { // TODO: warning if parsed bad
var instanceRange = this . _instance . range ;
var startDelta = diffDates ( instanceRange . start , start , dateEnv , options . granularity ) ; // what if parsed bad!?
if ( options . maintainDuration ) {
this . mutate ( { datesDelta : startDelta } ) ;
}
else {
this . mutate ( { startDelta : startDelta } ) ;
}
}
} ;
EventApi . prototype . setEnd = function ( endInput , options ) {
if ( options === void 0 ) { options = { } ; }
var dateEnv = this . _calendar . dateEnv ;
var end ;
if ( endInput != null ) {
end = dateEnv . createMarker ( endInput ) ;
if ( ! end ) {
return ; // TODO: warning if parsed bad
}
}
if ( this . _instance ) {
if ( end ) {
var endDelta = diffDates ( this . _instance . range . end , end , dateEnv , options . granularity ) ;
this . mutate ( { endDelta : endDelta } ) ;
}
else {
this . mutate ( { standardProps : { hasEnd : false } } ) ;
}
}
} ;
EventApi . prototype . setDates = function ( startInput , endInput , options ) {
if ( options === void 0 ) { options = { } ; }
var dateEnv = this . _calendar . dateEnv ;
var standardProps = { allDay : options . allDay } ;
var start = dateEnv . createMarker ( startInput ) ;
var end ;
if ( ! start ) {
return ; // TODO: warning if parsed bad
}
if ( endInput != null ) {
end = dateEnv . createMarker ( endInput ) ;
if ( ! end ) { // TODO: warning if parsed bad
return ;
}
}
if ( this . _instance ) {
var instanceRange = this . _instance . range ;
// when computing the diff for an event being converted to all-day,
// compute diff off of the all-day values the way event-mutation does.
if ( options . allDay === true ) {
instanceRange = computeAlignedDayRange ( instanceRange ) ;
}
var startDelta = diffDates ( instanceRange . start , start , dateEnv , options . granularity ) ;
if ( end ) {
var endDelta = diffDates ( instanceRange . end , end , dateEnv , options . granularity ) ;
if ( durationsEqual ( startDelta , endDelta ) ) {
this . mutate ( { datesDelta : startDelta , standardProps : standardProps } ) ;
}
else {
this . mutate ( { startDelta : startDelta , endDelta : endDelta , standardProps : standardProps } ) ;
}
}
else { // means "clear the end"
standardProps . hasEnd = false ;
this . mutate ( { datesDelta : startDelta , standardProps : standardProps } ) ;
}
}
} ;
EventApi . prototype . moveStart = function ( deltaInput ) {
var delta = createDuration ( deltaInput ) ;
if ( delta ) { // TODO: warning if parsed bad
this . mutate ( { startDelta : delta } ) ;
}
} ;
EventApi . prototype . moveEnd = function ( deltaInput ) {
var delta = createDuration ( deltaInput ) ;
if ( delta ) { // TODO: warning if parsed bad
this . mutate ( { endDelta : delta } ) ;
}
} ;
EventApi . prototype . moveDates = function ( deltaInput ) {
var delta = createDuration ( deltaInput ) ;
if ( delta ) { // TODO: warning if parsed bad
this . mutate ( { datesDelta : delta } ) ;
}
} ;
EventApi . prototype . setAllDay = function ( allDay , options ) {
if ( options === void 0 ) { options = { } ; }
var standardProps = { allDay : allDay } ;
var maintainDuration = options . maintainDuration ;
if ( maintainDuration == null ) {
maintainDuration = this . _calendar . opt ( 'allDayMaintainDuration' ) ;
}
if ( this . _def . allDay !== allDay ) {
standardProps . hasEnd = maintainDuration ;
}
this . mutate ( { standardProps : standardProps } ) ;
} ;
EventApi . prototype . formatRange = function ( formatInput ) {
var dateEnv = this . _calendar . dateEnv ;
var instance = this . _instance ;
var formatter = createFormatter ( formatInput , this . _calendar . opt ( 'defaultRangeSeparator' ) ) ;
if ( this . _def . hasEnd ) {
return dateEnv . formatRange ( instance . range . start , instance . range . end , formatter , {
forcedStartTzo : instance . forcedStartTzo ,
forcedEndTzo : instance . forcedEndTzo
} ) ;
}
else {
return dateEnv . format ( instance . range . start , formatter , {
forcedTzo : instance . forcedStartTzo
} ) ;
}
} ;
EventApi . prototype . mutate = function ( mutation ) {
var def = this . _def ;
var instance = this . _instance ;
if ( instance ) {
this . _calendar . dispatch ( {
type : 'MUTATE_EVENTS' ,
instanceId : instance . instanceId ,
mutation : mutation ,
fromApi : true
} ) ;
var eventStore = this . _calendar . state . eventStore ;
this . _def = eventStore . defs [ def . defId ] ;
this . _instance = eventStore . instances [ instance . instanceId ] ;
}
} ;
EventApi . prototype . remove = function ( ) {
this . _calendar . dispatch ( {
type : 'REMOVE_EVENT_DEF' ,
defId : this . _def . defId
} ) ;
} ;
Object . defineProperty ( EventApi . prototype , "source" , {
get : function ( ) {
var sourceId = this . _def . sourceId ;
if ( sourceId ) {
return new EventSourceApi ( this . _calendar , this . _calendar . state . eventSources [ sourceId ] ) ;
}
return null ;
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "start" , {
get : function ( ) {
return this . _instance ?
this . _calendar . dateEnv . toDate ( this . _instance . range . start ) :
null ;
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "end" , {
get : function ( ) {
return ( this . _instance && this . _def . hasEnd ) ?
this . _calendar . dateEnv . toDate ( this . _instance . range . end ) :
null ;
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "id" , {
// computable props that all access the def
// TODO: find a TypeScript-compatible way to do this at scale
get : function ( ) { return this . _def . publicId ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "groupId" , {
get : function ( ) { return this . _def . groupId ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "allDay" , {
get : function ( ) { return this . _def . allDay ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "title" , {
get : function ( ) { return this . _def . title ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "url" , {
get : function ( ) { return this . _def . url ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "rendering" , {
get : function ( ) { return this . _def . rendering ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "startEditable" , {
get : function ( ) { return this . _def . ui . startEditable ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "durationEditable" , {
get : function ( ) { return this . _def . ui . durationEditable ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "constraint" , {
get : function ( ) { return this . _def . ui . constraints [ 0 ] || null ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "overlap" , {
get : function ( ) { return this . _def . ui . overlap ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "allow" , {
get : function ( ) { return this . _def . ui . allows [ 0 ] || null ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "backgroundColor" , {
get : function ( ) { return this . _def . ui . backgroundColor ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "borderColor" , {
get : function ( ) { return this . _def . ui . borderColor ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "textColor" , {
get : function ( ) { return this . _def . ui . textColor ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "classNames" , {
// NOTE: user can't modify these because Object.freeze was called in event-def parsing
get : function ( ) { return this . _def . ui . classNames ; } ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( EventApi . prototype , "extendedProps" , {
get : function ( ) { return this . _def . extendedProps ; } ,
enumerable : true ,
configurable : true
} ) ;
return EventApi ;
} ( ) ) ;
/ *
Specifying nextDayThreshold signals that all - day ranges should be sliced .
* /
function sliceEventStore ( eventStore , eventUiBases , framingRange , nextDayThreshold ) {
var inverseBgByGroupId = { } ;
var inverseBgByDefId = { } ;
var defByGroupId = { } ;
var bgRanges = [ ] ;
var fgRanges = [ ] ;
var eventUis = compileEventUis ( eventStore . defs , eventUiBases ) ;
for ( var defId in eventStore . defs ) {
var def = eventStore . defs [ defId ] ;
if ( def . rendering === 'inverse-background' ) {
if ( def . groupId ) {
inverseBgByGroupId [ def . groupId ] = [ ] ;
if ( ! defByGroupId [ def . groupId ] ) {
defByGroupId [ def . groupId ] = def ;
}
}
else {
inverseBgByDefId [ defId ] = [ ] ;
}
}
}
for ( var instanceId in eventStore . instances ) {
var instance = eventStore . instances [ instanceId ] ;
var def = eventStore . defs [ instance . defId ] ;
var ui = eventUis [ def . defId ] ;
var origRange = instance . range ;
var normalRange = ( ! def . allDay && nextDayThreshold ) ?
computeVisibleDayRange ( origRange , nextDayThreshold ) :
origRange ;
var slicedRange = intersectRanges ( normalRange , framingRange ) ;
if ( slicedRange ) {
if ( def . rendering === 'inverse-background' ) {
if ( def . groupId ) {
inverseBgByGroupId [ def . groupId ] . push ( slicedRange ) ;
}
else {
inverseBgByDefId [ instance . defId ] . push ( slicedRange ) ;
}
}
else {
( def . rendering === 'background' ? bgRanges : fgRanges ) . push ( {
def : def ,
ui : ui ,
instance : instance ,
range : slicedRange ,
isStart : normalRange . start && normalRange . start . valueOf ( ) === slicedRange . start . valueOf ( ) ,
isEnd : normalRange . end && normalRange . end . valueOf ( ) === slicedRange . end . valueOf ( )
} ) ;
}
}
}
for ( var groupId in inverseBgByGroupId ) { // BY GROUP
var ranges = inverseBgByGroupId [ groupId ] ;
var invertedRanges = invertRanges ( ranges , framingRange ) ;
for ( var _i = 0 , invertedRanges _1 = invertedRanges ; _i < invertedRanges _1 . length ; _i ++ ) {
var invertedRange = invertedRanges _1 [ _i ] ;
var def = defByGroupId [ groupId ] ;
var ui = eventUis [ def . defId ] ;
bgRanges . push ( {
def : def ,
ui : ui ,
instance : null ,
range : invertedRange ,
isStart : false ,
isEnd : false
} ) ;
}
}
for ( var defId in inverseBgByDefId ) {
var ranges = inverseBgByDefId [ defId ] ;
var invertedRanges = invertRanges ( ranges , framingRange ) ;
for ( var _a = 0 , invertedRanges _2 = invertedRanges ; _a < invertedRanges _2 . length ; _a ++ ) {
var invertedRange = invertedRanges _2 [ _a ] ;
bgRanges . push ( {
def : eventStore . defs [ defId ] ,
ui : eventUis [ defId ] ,
instance : null ,
range : invertedRange ,
isStart : false ,
isEnd : false
} ) ;
}
}
return { bg : bgRanges , fg : fgRanges } ;
}
function hasBgRendering ( def ) {
return def . rendering === 'background' || def . rendering === 'inverse-background' ;
}
2020-04-01 22:52:43 +00:00
function filterSegsViaEls ( context , segs , isMirror ) {
var calendar = context . calendar , view = context . view ;
if ( calendar . hasPublicHandlers ( 'eventRender' ) ) {
2019-08-28 10:59:33 +00:00
segs = segs . filter ( function ( seg ) {
2020-04-01 22:52:43 +00:00
var custom = calendar . publiclyTrigger ( 'eventRender' , [
2019-08-28 10:59:33 +00:00
{
2020-04-01 22:52:43 +00:00
event : new EventApi ( calendar , seg . eventRange . def , seg . eventRange . instance ) ,
2019-08-28 10:59:33 +00:00
isMirror : isMirror ,
isStart : seg . isStart ,
isEnd : seg . isEnd ,
// TODO: include seg.range once all components consistently generate it
el : seg . el ,
view : view
}
] ) ;
if ( custom === false ) { // means don't render at all
return false ;
}
else if ( custom && custom !== true ) {
seg . el = custom ;
}
return true ;
} ) ;
}
for ( var _i = 0 , segs _1 = segs ; _i < segs _1 . length ; _i ++ ) {
var seg = segs _1 [ _i ] ;
setElSeg ( seg . el , seg ) ;
}
return segs ;
}
function setElSeg ( el , seg ) {
el . fcSeg = seg ;
}
function getElSeg ( el ) {
return el . fcSeg || null ;
}
// event ui computation
function compileEventUis ( eventDefs , eventUiBases ) {
return mapHash ( eventDefs , function ( eventDef ) {
return compileEventUi ( eventDef , eventUiBases ) ;
} ) ;
}
function compileEventUi ( eventDef , eventUiBases ) {
var uis = [ ] ;
if ( eventUiBases [ '' ] ) {
uis . push ( eventUiBases [ '' ] ) ;
}
if ( eventUiBases [ eventDef . defId ] ) {
uis . push ( eventUiBases [ eventDef . defId ] ) ;
}
uis . push ( eventDef . ui ) ;
return combineEventUis ( uis ) ;
}
2020-04-01 22:52:43 +00:00
// triggers
function triggerRenderedSegs ( context , segs , isMirrors ) {
var calendar = context . calendar , view = context . view ;
if ( calendar . hasPublicHandlers ( 'eventPositioned' ) ) {
for ( var _i = 0 , segs _2 = segs ; _i < segs _2 . length ; _i ++ ) {
var seg = segs _2 [ _i ] ;
calendar . publiclyTriggerAfterSizing ( 'eventPositioned' , [
{
event : new EventApi ( calendar , seg . eventRange . def , seg . eventRange . instance ) ,
isMirror : isMirrors ,
isStart : seg . isStart ,
isEnd : seg . isEnd ,
el : seg . el ,
view : view
}
] ) ;
}
}
2020-06-01 11:05:25 +00:00
if ( ! calendar . state . eventSourceLoadingLevel ) { // avoid initial empty state while pending
2020-04-01 22:52:43 +00:00
calendar . afterSizingTriggers . _eventsPositioned = [ null ] ; // fire once
}
}
function triggerWillRemoveSegs ( context , segs , isMirrors ) {
var calendar = context . calendar , view = context . view ;
for ( var _i = 0 , segs _3 = segs ; _i < segs _3 . length ; _i ++ ) {
var seg = segs _3 [ _i ] ;
calendar . trigger ( 'eventElRemove' , seg . el ) ;
}
if ( calendar . hasPublicHandlers ( 'eventDestroy' ) ) {
for ( var _a = 0 , segs _4 = segs ; _a < segs _4 . length ; _a ++ ) {
var seg = segs _4 [ _a ] ;
calendar . publiclyTrigger ( 'eventDestroy' , [
{
event : new EventApi ( calendar , seg . eventRange . def , seg . eventRange . instance ) ,
isMirror : isMirrors ,
el : seg . el ,
view : view
}
] ) ;
}
}
}
// is-interactable
function computeEventDraggable ( context , eventDef , eventUi ) {
var calendar = context . calendar , view = context . view ;
var transformers = calendar . pluginSystem . hooks . isDraggableTransformers ;
var val = eventUi . startEditable ;
for ( var _i = 0 , transformers _1 = transformers ; _i < transformers _1 . length ; _i ++ ) {
var transformer = transformers _1 [ _i ] ;
val = transformer ( val , eventDef , eventUi , view ) ;
}
return val ;
}
function computeEventStartResizable ( context , eventDef , eventUi ) {
return eventUi . durationEditable && context . options . eventResizableFromStart ;
}
function computeEventEndResizable ( context , eventDef , eventUi ) {
return eventUi . durationEditable ;
}
2019-08-28 10:59:33 +00:00
// applies the mutation to ALL defs/instances within the event store
function applyMutationToEventStore ( eventStore , eventConfigBase , mutation , calendar ) {
var eventConfigs = compileEventUis ( eventStore . defs , eventConfigBase ) ;
var dest = createEmptyEventStore ( ) ;
for ( var defId in eventStore . defs ) {
var def = eventStore . defs [ defId ] ;
dest . defs [ defId ] = applyMutationToEventDef ( def , eventConfigs [ defId ] , mutation , calendar . pluginSystem . hooks . eventDefMutationAppliers , calendar ) ;
}
for ( var instanceId in eventStore . instances ) {
var instance = eventStore . instances [ instanceId ] ;
var def = dest . defs [ instance . defId ] ; // important to grab the newly modified def
dest . instances [ instanceId ] = applyMutationToEventInstance ( instance , def , eventConfigs [ instance . defId ] , mutation , calendar ) ;
}
return dest ;
}
function applyMutationToEventDef ( eventDef , eventConfig , mutation , appliers , calendar ) {
var standardProps = mutation . standardProps || { } ;
// if hasEnd has not been specified, guess a good value based on deltas.
// if duration will change, there's no way the default duration will persist,
// and thus, we need to mark the event as having a real end
if ( standardProps . hasEnd == null &&
eventConfig . durationEditable &&
( mutation . startDelta || mutation . endDelta ) ) {
standardProps . hasEnd = true ; // TODO: is this mutation okay?
}
var copy = _ _assign ( { } , eventDef , standardProps , { ui : _ _assign ( { } , eventDef . ui , standardProps . ui ) } ) ;
if ( mutation . extendedProps ) {
copy . extendedProps = _ _assign ( { } , copy . extendedProps , mutation . extendedProps ) ;
}
for ( var _i = 0 , appliers _1 = appliers ; _i < appliers _1 . length ; _i ++ ) {
var applier = appliers _1 [ _i ] ;
applier ( copy , mutation , calendar ) ;
}
if ( ! copy . hasEnd && calendar . opt ( 'forceEventDuration' ) ) {
copy . hasEnd = true ;
}
return copy ;
}
function applyMutationToEventInstance ( eventInstance , eventDef , // must first be modified by applyMutationToEventDef
eventConfig , mutation , calendar ) {
var dateEnv = calendar . dateEnv ;
var forceAllDay = mutation . standardProps && mutation . standardProps . allDay === true ;
var clearEnd = mutation . standardProps && mutation . standardProps . hasEnd === false ;
var copy = _ _assign ( { } , eventInstance ) ;
if ( forceAllDay ) {
copy . range = computeAlignedDayRange ( copy . range ) ;
}
if ( mutation . datesDelta && eventConfig . startEditable ) {
copy . range = {
start : dateEnv . add ( copy . range . start , mutation . datesDelta ) ,
end : dateEnv . add ( copy . range . end , mutation . datesDelta )
} ;
}
if ( mutation . startDelta && eventConfig . durationEditable ) {
copy . range = {
start : dateEnv . add ( copy . range . start , mutation . startDelta ) ,
end : copy . range . end
} ;
}
if ( mutation . endDelta && eventConfig . durationEditable ) {
copy . range = {
start : copy . range . start ,
end : dateEnv . add ( copy . range . end , mutation . endDelta )
} ;
}
if ( clearEnd ) {
copy . range = {
start : copy . range . start ,
end : calendar . getDefaultEventEnd ( eventDef . allDay , copy . range . start )
} ;
}
// in case event was all-day but the supplied deltas were not
// better util for this?
if ( eventDef . allDay ) {
copy . range = {
start : startOfDay ( copy . range . start ) ,
end : startOfDay ( copy . range . end )
} ;
}
// handle invalid durations
if ( copy . range . end < copy . range . start ) {
copy . range . end = calendar . getDefaultEventEnd ( eventDef . allDay , copy . range . start ) ;
}
return copy ;
}
function reduceEventStore ( eventStore , action , eventSources , dateProfile , calendar ) {
switch ( action . type ) {
case 'RECEIVE_EVENTS' : // raw
return receiveRawEvents ( eventStore , eventSources [ action . sourceId ] , action . fetchId , action . fetchRange , action . rawEvents , calendar ) ;
case 'ADD_EVENTS' : // already parsed, but not expanded
return addEvent ( eventStore , action . eventStore , // new ones
dateProfile ? dateProfile . activeRange : null , calendar ) ;
case 'MERGE_EVENTS' : // already parsed and expanded
return mergeEventStores ( eventStore , action . eventStore ) ;
case 'PREV' : // TODO: how do we track all actions that affect dateProfile :(
case 'NEXT' :
case 'SET_DATE' :
case 'SET_VIEW_TYPE' :
if ( dateProfile ) {
return expandRecurring ( eventStore , dateProfile . activeRange , calendar ) ;
}
else {
return eventStore ;
}
case 'CHANGE_TIMEZONE' :
return rezoneDates ( eventStore , action . oldDateEnv , calendar . dateEnv ) ;
case 'MUTATE_EVENTS' :
return applyMutationToRelated ( eventStore , action . instanceId , action . mutation , action . fromApi , calendar ) ;
case 'REMOVE_EVENT_INSTANCES' :
return excludeInstances ( eventStore , action . instances ) ;
case 'REMOVE_EVENT_DEF' :
return filterEventStoreDefs ( eventStore , function ( eventDef ) {
return eventDef . defId !== action . defId ;
} ) ;
case 'REMOVE_EVENT_SOURCE' :
return excludeEventsBySourceId ( eventStore , action . sourceId ) ;
case 'REMOVE_ALL_EVENT_SOURCES' :
return filterEventStoreDefs ( eventStore , function ( eventDef ) {
return ! eventDef . sourceId ; // only keep events with no source id
} ) ;
case 'REMOVE_ALL_EVENTS' :
return createEmptyEventStore ( ) ;
case 'RESET_EVENTS' :
return {
defs : eventStore . defs ,
instances : eventStore . instances
} ;
default :
return eventStore ;
}
}
function receiveRawEvents ( eventStore , eventSource , fetchId , fetchRange , rawEvents , calendar ) {
if ( eventSource && // not already removed
fetchId === eventSource . latestFetchId // TODO: wish this logic was always in event-sources
) {
var subset = parseEvents ( transformRawEvents ( rawEvents , eventSource , calendar ) , eventSource . sourceId , calendar ) ;
if ( fetchRange ) {
subset = expandRecurring ( subset , fetchRange , calendar ) ;
}
return mergeEventStores ( excludeEventsBySourceId ( eventStore , eventSource . sourceId ) , subset ) ;
}
return eventStore ;
}
function addEvent ( eventStore , subset , expandRange , calendar ) {
if ( expandRange ) {
subset = expandRecurring ( subset , expandRange , calendar ) ;
}
return mergeEventStores ( eventStore , subset ) ;
}
function rezoneDates ( eventStore , oldDateEnv , newDateEnv ) {
var defs = eventStore . defs ;
var instances = mapHash ( eventStore . instances , function ( instance ) {
var def = defs [ instance . defId ] ;
if ( def . allDay || def . recurringDef ) {
return instance ; // isn't dependent on timezone
}
else {
return _ _assign ( { } , instance , { range : {
start : newDateEnv . createMarker ( oldDateEnv . toDate ( instance . range . start , instance . forcedStartTzo ) ) ,
end : newDateEnv . createMarker ( oldDateEnv . toDate ( instance . range . end , instance . forcedEndTzo ) )
} , forcedStartTzo : newDateEnv . canComputeOffset ? null : instance . forcedStartTzo , forcedEndTzo : newDateEnv . canComputeOffset ? null : instance . forcedEndTzo } ) ;
}
} ) ;
return { defs : defs , instances : instances } ;
}
function applyMutationToRelated ( eventStore , instanceId , mutation , fromApi , calendar ) {
var relevant = getRelevantEvents ( eventStore , instanceId ) ;
var eventConfigBase = fromApi ?
{ '' : {
startEditable : true ,
durationEditable : true ,
constraints : [ ] ,
overlap : null ,
allows : [ ] ,
backgroundColor : '' ,
borderColor : '' ,
textColor : '' ,
classNames : [ ]
} } :
calendar . eventUiBases ;
relevant = applyMutationToEventStore ( relevant , eventConfigBase , mutation , calendar ) ;
return mergeEventStores ( eventStore , relevant ) ;
}
function excludeEventsBySourceId ( eventStore , sourceId ) {
return filterEventStoreDefs ( eventStore , function ( eventDef ) {
return eventDef . sourceId !== sourceId ;
} ) ;
}
// QUESTION: why not just return instances? do a general object-property-exclusion util
function excludeInstances ( eventStore , removals ) {
return {
defs : eventStore . defs ,
instances : filterHash ( eventStore . instances , function ( instance ) {
return ! removals [ instance . instanceId ] ;
} )
} ;
}
// high-level segmenting-aware tester functions
// ------------------------------------------------------------------------------------------------------------------------
function isInteractionValid ( interaction , calendar ) {
return isNewPropsValid ( { eventDrag : interaction } , calendar ) ; // HACK: the eventDrag props is used for ALL interactions
}
function isDateSelectionValid ( dateSelection , calendar ) {
return isNewPropsValid ( { dateSelection : dateSelection } , calendar ) ;
}
function isNewPropsValid ( newProps , calendar ) {
var view = calendar . view ;
var props = _ _assign ( { businessHours : view ? view . props . businessHours : createEmptyEventStore ( ) , dateSelection : '' , eventStore : calendar . state . eventStore , eventUiBases : calendar . eventUiBases , eventSelection : '' , eventDrag : null , eventResize : null } , newProps ) ;
return ( calendar . pluginSystem . hooks . isPropsValid || isPropsValid ) ( props , calendar ) ;
}
function isPropsValid ( state , calendar , dateSpanMeta , filterConfig ) {
if ( dateSpanMeta === void 0 ) { dateSpanMeta = { } ; }
if ( state . eventDrag && ! isInteractionPropsValid ( state , calendar , dateSpanMeta , filterConfig ) ) {
return false ;
}
if ( state . dateSelection && ! isDateSelectionPropsValid ( state , calendar , dateSpanMeta , filterConfig ) ) {
return false ;
}
return true ;
}
// Moving Event Validation
// ------------------------------------------------------------------------------------------------------------------------
function isInteractionPropsValid ( state , calendar , dateSpanMeta , filterConfig ) {
var interaction = state . eventDrag ; // HACK: the eventDrag props is used for ALL interactions
var subjectEventStore = interaction . mutatedEvents ;
var subjectDefs = subjectEventStore . defs ;
var subjectInstances = subjectEventStore . instances ;
var subjectConfigs = compileEventUis ( subjectDefs , interaction . isEvent ?
state . eventUiBases :
{ '' : calendar . selectionConfig } // if not a real event, validate as a selection
) ;
if ( filterConfig ) {
subjectConfigs = mapHash ( subjectConfigs , filterConfig ) ;
}
var otherEventStore = excludeInstances ( state . eventStore , interaction . affectedEvents . instances ) ; // exclude the subject events. TODO: exclude defs too?
var otherDefs = otherEventStore . defs ;
var otherInstances = otherEventStore . instances ;
var otherConfigs = compileEventUis ( otherDefs , state . eventUiBases ) ;
for ( var subjectInstanceId in subjectInstances ) {
var subjectInstance = subjectInstances [ subjectInstanceId ] ;
var subjectRange = subjectInstance . range ;
var subjectConfig = subjectConfigs [ subjectInstance . defId ] ;
var subjectDef = subjectDefs [ subjectInstance . defId ] ;
// constraint
if ( ! allConstraintsPass ( subjectConfig . constraints , subjectRange , otherEventStore , state . businessHours , calendar ) ) {
return false ;
}
// overlap
var overlapFunc = calendar . opt ( 'eventOverlap' ) ;
if ( typeof overlapFunc !== 'function' ) {
overlapFunc = null ;
}
for ( var otherInstanceId in otherInstances ) {
var otherInstance = otherInstances [ otherInstanceId ] ;
// intersect! evaluate
if ( rangesIntersect ( subjectRange , otherInstance . range ) ) {
var otherOverlap = otherConfigs [ otherInstance . defId ] . overlap ;
// consider the other event's overlap. only do this if the subject event is a "real" event
if ( otherOverlap === false && interaction . isEvent ) {
return false ;
}
if ( subjectConfig . overlap === false ) {
return false ;
}
if ( overlapFunc && ! overlapFunc ( new EventApi ( calendar , otherDefs [ otherInstance . defId ] , otherInstance ) , // still event
new EventApi ( calendar , subjectDef , subjectInstance ) // moving event
) ) {
return false ;
}
}
}
// allow (a function)
var calendarEventStore = calendar . state . eventStore ; // need global-to-calendar, not local to component (splittable)state
for ( var _i = 0 , _a = subjectConfig . allows ; _i < _a . length ; _i ++ ) {
var subjectAllow = _a [ _i ] ;
var subjectDateSpan = _ _assign ( { } , dateSpanMeta , { range : subjectInstance . range , allDay : subjectDef . allDay } ) ;
var origDef = calendarEventStore . defs [ subjectDef . defId ] ;
var origInstance = calendarEventStore . instances [ subjectInstanceId ] ;
var eventApi = void 0 ;
if ( origDef ) { // was previously in the calendar
eventApi = new EventApi ( calendar , origDef , origInstance ) ;
}
else { // was an external event
eventApi = new EventApi ( calendar , subjectDef ) ; // no instance, because had no dates
}
if ( ! subjectAllow ( calendar . buildDateSpanApi ( subjectDateSpan ) , eventApi ) ) {
return false ;
}
}
}
return true ;
}
// Date Selection Validation
// ------------------------------------------------------------------------------------------------------------------------
function isDateSelectionPropsValid ( state , calendar , dateSpanMeta , filterConfig ) {
var relevantEventStore = state . eventStore ;
var relevantDefs = relevantEventStore . defs ;
var relevantInstances = relevantEventStore . instances ;
var selection = state . dateSelection ;
var selectionRange = selection . range ;
var selectionConfig = calendar . selectionConfig ;
if ( filterConfig ) {
selectionConfig = filterConfig ( selectionConfig ) ;
}
// constraint
if ( ! allConstraintsPass ( selectionConfig . constraints , selectionRange , relevantEventStore , state . businessHours , calendar ) ) {
return false ;
}
// overlap
var overlapFunc = calendar . opt ( 'selectOverlap' ) ;
if ( typeof overlapFunc !== 'function' ) {
overlapFunc = null ;
}
for ( var relevantInstanceId in relevantInstances ) {
var relevantInstance = relevantInstances [ relevantInstanceId ] ;
// intersect! evaluate
if ( rangesIntersect ( selectionRange , relevantInstance . range ) ) {
if ( selectionConfig . overlap === false ) {
return false ;
}
if ( overlapFunc && ! overlapFunc ( new EventApi ( calendar , relevantDefs [ relevantInstance . defId ] , relevantInstance ) ) ) {
return false ;
}
}
}
// allow (a function)
for ( var _i = 0 , _a = selectionConfig . allows ; _i < _a . length ; _i ++ ) {
var selectionAllow = _a [ _i ] ;
var fullDateSpan = _ _assign ( { } , dateSpanMeta , selection ) ;
if ( ! selectionAllow ( calendar . buildDateSpanApi ( fullDateSpan ) , null ) ) {
return false ;
}
}
return true ;
}
// Constraint Utils
// ------------------------------------------------------------------------------------------------------------------------
function allConstraintsPass ( constraints , subjectRange , otherEventStore , businessHoursUnexpanded , calendar ) {
for ( var _i = 0 , constraints _1 = constraints ; _i < constraints _1 . length ; _i ++ ) {
var constraint = constraints _1 [ _i ] ;
if ( ! anyRangesContainRange ( constraintToRanges ( constraint , subjectRange , otherEventStore , businessHoursUnexpanded , calendar ) , subjectRange ) ) {
return false ;
}
}
return true ;
}
function constraintToRanges ( constraint , subjectRange , // for expanding a recurring constraint, or expanding business hours
otherEventStore , // for if constraint is an even group ID
businessHoursUnexpanded , // for if constraint is 'businessHours'
calendar // for expanding businesshours
) {
if ( constraint === 'businessHours' ) {
return eventStoreToRanges ( expandRecurring ( businessHoursUnexpanded , subjectRange , calendar ) ) ;
}
else if ( typeof constraint === 'string' ) { // an group ID
return eventStoreToRanges ( filterEventStoreDefs ( otherEventStore , function ( eventDef ) {
return eventDef . groupId === constraint ;
} ) ) ;
}
else if ( typeof constraint === 'object' && constraint ) { // non-null object
return eventStoreToRanges ( expandRecurring ( constraint , subjectRange , calendar ) ) ;
}
return [ ] ; // if it's false
}
// TODO: move to event-store file?
function eventStoreToRanges ( eventStore ) {
var instances = eventStore . instances ;
var ranges = [ ] ;
for ( var instanceId in instances ) {
ranges . push ( instances [ instanceId ] . range ) ;
}
return ranges ;
}
// TODO: move to geom file?
function anyRangesContainRange ( outerRanges , innerRange ) {
for ( var _i = 0 , outerRanges _1 = outerRanges ; _i < outerRanges _1 . length ; _i ++ ) {
var outerRange = outerRanges _1 [ _i ] ;
if ( rangeContainsRange ( outerRange , innerRange ) ) {
return true ;
}
}
return false ;
}
// Parsing
// ------------------------------------------------------------------------------------------------------------------------
function normalizeConstraint ( input , calendar ) {
if ( Array . isArray ( input ) ) {
return parseEvents ( input , '' , calendar , true ) ; // allowOpenRange=true
}
else if ( typeof input === 'object' && input ) { // non-null object
return parseEvents ( [ input ] , '' , calendar , true ) ; // allowOpenRange=true
}
else if ( input != null ) {
return String ( input ) ;
}
else {
return null ;
}
}
function htmlEscape ( s ) {
return ( s + '' ) . replace ( /&/g , '&' )
. replace ( /</g , '<' )
. replace ( />/g , '>' )
. replace ( /'/g , ''' )
. replace ( /"/g , '"' )
. replace ( /\n/g , '<br />' ) ;
}
// Given a hash of CSS properties, returns a string of CSS.
// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values.
function cssToStr ( cssProps ) {
var statements = [ ] ;
for ( var name _1 in cssProps ) {
var val = cssProps [ name _1 ] ;
if ( val != null && val !== '' ) {
statements . push ( name _1 + ':' + val ) ;
}
}
return statements . join ( ';' ) ;
}
// Given an object hash of HTML attribute names to values,
// generates a string that can be injected between < > in HTML
function attrsToStr ( attrs ) {
var parts = [ ] ;
for ( var name _2 in attrs ) {
var val = attrs [ name _2 ] ;
if ( val != null ) {
parts . push ( name _2 + '="' + htmlEscape ( val ) + '"' ) ;
}
}
return parts . join ( ' ' ) ;
}
function parseClassName ( raw ) {
if ( Array . isArray ( raw ) ) {
return raw ;
}
else if ( typeof raw === 'string' ) {
return raw . split ( /\s+/ ) ;
}
else {
return [ ] ;
}
}
var UNSCOPED _EVENT _UI _PROPS = {
editable : Boolean ,
startEditable : Boolean ,
durationEditable : Boolean ,
constraint : null ,
overlap : null ,
allow : null ,
className : parseClassName ,
classNames : parseClassName ,
color : String ,
backgroundColor : String ,
borderColor : String ,
textColor : String
} ;
function processUnscopedUiProps ( rawProps , calendar , leftovers ) {
var props = refineProps ( rawProps , UNSCOPED _EVENT _UI _PROPS , { } , leftovers ) ;
var constraint = normalizeConstraint ( props . constraint , calendar ) ;
return {
startEditable : props . startEditable != null ? props . startEditable : props . editable ,
durationEditable : props . durationEditable != null ? props . durationEditable : props . editable ,
constraints : constraint != null ? [ constraint ] : [ ] ,
overlap : props . overlap ,
allows : props . allow != null ? [ props . allow ] : [ ] ,
backgroundColor : props . backgroundColor || props . color ,
borderColor : props . borderColor || props . color ,
textColor : props . textColor ,
classNames : props . classNames . concat ( props . className )
} ;
}
function processScopedUiProps ( prefix , rawScoped , calendar , leftovers ) {
var rawUnscoped = { } ;
var wasFound = { } ;
for ( var key in UNSCOPED _EVENT _UI _PROPS ) {
var scopedKey = prefix + capitaliseFirstLetter ( key ) ;
rawUnscoped [ key ] = rawScoped [ scopedKey ] ;
wasFound [ scopedKey ] = true ;
}
if ( prefix === 'event' ) {
rawUnscoped . editable = rawScoped . editable ; // special case. there is no 'eventEditable', just 'editable'
}
if ( leftovers ) {
for ( var key in rawScoped ) {
if ( ! wasFound [ key ] ) {
leftovers [ key ] = rawScoped [ key ] ;
}
}
}
return processUnscopedUiProps ( rawUnscoped , calendar ) ;
}
var EMPTY _EVENT _UI = {
startEditable : null ,
durationEditable : null ,
constraints : [ ] ,
overlap : null ,
allows : [ ] ,
backgroundColor : '' ,
borderColor : '' ,
textColor : '' ,
classNames : [ ]
} ;
// prevent against problems with <2 args!
function combineEventUis ( uis ) {
return uis . reduce ( combineTwoEventUis , EMPTY _EVENT _UI ) ;
}
function combineTwoEventUis ( item0 , item1 ) {
return {
startEditable : item1 . startEditable != null ? item1 . startEditable : item0 . startEditable ,
durationEditable : item1 . durationEditable != null ? item1 . durationEditable : item0 . durationEditable ,
constraints : item0 . constraints . concat ( item1 . constraints ) ,
overlap : typeof item1 . overlap === 'boolean' ? item1 . overlap : item0 . overlap ,
allows : item0 . allows . concat ( item1 . allows ) ,
backgroundColor : item1 . backgroundColor || item0 . backgroundColor ,
borderColor : item1 . borderColor || item0 . borderColor ,
textColor : item1 . textColor || item0 . textColor ,
classNames : item0 . classNames . concat ( item1 . classNames )
} ;
}
var NON _DATE _PROPS = {
id : String ,
groupId : String ,
title : String ,
url : String ,
rendering : String ,
extendedProps : null
} ;
var DATE _PROPS = {
start : null ,
date : null ,
end : null ,
allDay : null
} ;
var uid = 0 ;
function parseEvent ( raw , sourceId , calendar , allowOpenRange ) {
var allDayDefault = computeIsAllDayDefault ( sourceId , calendar ) ;
var leftovers0 = { } ;
var recurringRes = parseRecurring ( raw , // raw, but with single-event stuff stripped out
allDayDefault , calendar . dateEnv , calendar . pluginSystem . hooks . recurringTypes , leftovers0 // will populate with non-recurring props
) ;
if ( recurringRes ) {
var def = parseEventDef ( leftovers0 , sourceId , recurringRes . allDay , Boolean ( recurringRes . duration ) , calendar ) ;
def . recurringDef = {
typeId : recurringRes . typeId ,
typeData : recurringRes . typeData ,
duration : recurringRes . duration
} ;
return { def : def , instance : null } ;
}
else {
var leftovers1 = { } ;
var singleRes = parseSingle ( raw , allDayDefault , calendar , leftovers1 , allowOpenRange ) ;
if ( singleRes ) {
var def = parseEventDef ( leftovers1 , sourceId , singleRes . allDay , singleRes . hasEnd , calendar ) ;
var instance = createEventInstance ( def . defId , singleRes . range , singleRes . forcedStartTzo , singleRes . forcedEndTzo ) ;
return { def : def , instance : instance } ;
}
}
return null ;
}
/ *
Will NOT populate extendedProps with the leftover properties .
Will NOT populate date - related props .
The EventNonDateInput has been normalized ( id => publicId , etc ) .
* /
function parseEventDef ( raw , sourceId , allDay , hasEnd , calendar ) {
var leftovers = { } ;
var def = pluckNonDateProps ( raw , calendar , leftovers ) ;
def . defId = String ( uid ++ ) ;
def . sourceId = sourceId ;
def . allDay = allDay ;
def . hasEnd = hasEnd ;
for ( var _i = 0 , _a = calendar . pluginSystem . hooks . eventDefParsers ; _i < _a . length ; _i ++ ) {
var eventDefParser = _a [ _i ] ;
var newLeftovers = { } ;
eventDefParser ( def , leftovers , newLeftovers ) ;
leftovers = newLeftovers ;
}
def . extendedProps = _ _assign ( leftovers , def . extendedProps || { } ) ;
// help out EventApi from having user modify props
Object . freeze ( def . ui . classNames ) ;
Object . freeze ( def . extendedProps ) ;
return def ;
}
function createEventInstance ( defId , range , forcedStartTzo , forcedEndTzo ) {
return {
instanceId : String ( uid ++ ) ,
defId : defId ,
range : range ,
forcedStartTzo : forcedStartTzo == null ? null : forcedStartTzo ,
forcedEndTzo : forcedEndTzo == null ? null : forcedEndTzo
} ;
}
function parseSingle ( raw , allDayDefault , calendar , leftovers , allowOpenRange ) {
var props = pluckDateProps ( raw , leftovers ) ;
var allDay = props . allDay ;
var startMeta ;
var startMarker = null ;
var hasEnd = false ;
var endMeta ;
var endMarker = null ;
startMeta = calendar . dateEnv . createMarkerMeta ( props . start ) ;
if ( startMeta ) {
startMarker = startMeta . marker ;
}
else if ( ! allowOpenRange ) {
return null ;
}
if ( props . end != null ) {
endMeta = calendar . dateEnv . createMarkerMeta ( props . end ) ;
}
if ( allDay == null ) {
if ( allDayDefault != null ) {
allDay = allDayDefault ;
}
else {
// fall back to the date props LAST
allDay = ( ! startMeta || startMeta . isTimeUnspecified ) &&
( ! endMeta || endMeta . isTimeUnspecified ) ;
}
}
if ( allDay && startMarker ) {
startMarker = startOfDay ( startMarker ) ;
}
if ( endMeta ) {
endMarker = endMeta . marker ;
if ( allDay ) {
endMarker = startOfDay ( endMarker ) ;
}
if ( startMarker && endMarker <= startMarker ) {
endMarker = null ;
}
}
if ( endMarker ) {
hasEnd = true ;
}
else if ( ! allowOpenRange ) {
hasEnd = calendar . opt ( 'forceEventDuration' ) || false ;
endMarker = calendar . dateEnv . add ( startMarker , allDay ?
calendar . defaultAllDayEventDuration :
calendar . defaultTimedEventDuration ) ;
}
return {
allDay : allDay ,
hasEnd : hasEnd ,
range : { start : startMarker , end : endMarker } ,
forcedStartTzo : startMeta ? startMeta . forcedTzo : null ,
forcedEndTzo : endMeta ? endMeta . forcedTzo : null
} ;
}
function pluckDateProps ( raw , leftovers ) {
var props = refineProps ( raw , DATE _PROPS , { } , leftovers ) ;
props . start = ( props . start !== null ) ? props . start : props . date ;
delete props . date ;
return props ;
}
function pluckNonDateProps ( raw , calendar , leftovers ) {
var preLeftovers = { } ;
var props = refineProps ( raw , NON _DATE _PROPS , { } , preLeftovers ) ;
var ui = processUnscopedUiProps ( preLeftovers , calendar , leftovers ) ;
props . publicId = props . id ;
delete props . id ;
props . ui = ui ;
return props ;
}
function computeIsAllDayDefault ( sourceId , calendar ) {
var res = null ;
if ( sourceId ) {
var source = calendar . state . eventSources [ sourceId ] ;
res = source . allDayDefault ;
}
if ( res == null ) {
res = calendar . opt ( 'allDayDefault' ) ;
}
return res ;
}
var DEF _DEFAULTS = {
startTime : '09:00' ,
endTime : '17:00' ,
daysOfWeek : [ 1 , 2 , 3 , 4 , 5 ] ,
rendering : 'inverse-background' ,
classNames : 'fc-nonbusiness' ,
groupId : '_businessHours' // so multiple defs get grouped
} ;
/ *
TODO : pass around as EventDefHash ! ! !
* /
function parseBusinessHours ( input , calendar ) {
return parseEvents ( refineInputs ( input ) , '' , calendar ) ;
}
function refineInputs ( input ) {
var rawDefs ;
if ( input === true ) {
rawDefs = [ { } ] ; // will get DEF_DEFAULTS verbatim
}
else if ( Array . isArray ( input ) ) {
// if specifying an array, every sub-definition NEEDS a day-of-week
rawDefs = input . filter ( function ( rawDef ) {
return rawDef . daysOfWeek ;
} ) ;
}
else if ( typeof input === 'object' && input ) { // non-null object
rawDefs = [ input ] ;
}
else { // is probably false
rawDefs = [ ] ;
}
rawDefs = rawDefs . map ( function ( rawDef ) {
return _ _assign ( { } , DEF _DEFAULTS , rawDef ) ;
} ) ;
return rawDefs ;
}
function memoizeRendering ( renderFunc , unrenderFunc , dependencies ) {
if ( dependencies === void 0 ) { dependencies = [ ] ; }
var dependents = [ ] ;
var thisContext ;
var prevArgs ;
function unrender ( ) {
if ( prevArgs ) {
for ( var _i = 0 , dependents _1 = dependents ; _i < dependents _1 . length ; _i ++ ) {
var dependent = dependents _1 [ _i ] ;
dependent . unrender ( ) ;
}
if ( unrenderFunc ) {
unrenderFunc . apply ( thisContext , prevArgs ) ;
}
prevArgs = null ;
}
}
function res ( ) {
if ( ! prevArgs || ! isArraysEqual ( prevArgs , arguments ) ) {
unrender ( ) ;
thisContext = this ;
prevArgs = arguments ;
renderFunc . apply ( this , arguments ) ;
}
}
res . dependents = dependents ;
res . unrender = unrender ;
for ( var _i = 0 , dependencies _1 = dependencies ; _i < dependencies _1 . length ; _i ++ ) {
var dependency = dependencies _1 [ _i ] ;
dependency . dependents . push ( res ) ;
}
return res ;
}
var EMPTY _EVENT _STORE = createEmptyEventStore ( ) ; // for purecomponents. TODO: keep elsewhere
var Splitter = /** @class */ ( function ( ) {
function Splitter ( ) {
this . getKeysForEventDefs = memoize ( this . _getKeysForEventDefs ) ;
this . splitDateSelection = memoize ( this . _splitDateSpan ) ;
this . splitEventStore = memoize ( this . _splitEventStore ) ;
this . splitIndividualUi = memoize ( this . _splitIndividualUi ) ;
this . splitEventDrag = memoize ( this . _splitInteraction ) ;
this . splitEventResize = memoize ( this . _splitInteraction ) ;
this . eventUiBuilders = { } ; // TODO: typescript protection
}
Splitter . prototype . splitProps = function ( props ) {
var _this = this ;
var keyInfos = this . getKeyInfo ( props ) ;
var defKeys = this . getKeysForEventDefs ( props . eventStore ) ;
var dateSelections = this . splitDateSelection ( props . dateSelection ) ;
var individualUi = this . splitIndividualUi ( props . eventUiBases , defKeys ) ; // the individual *bases*
var eventStores = this . splitEventStore ( props . eventStore , defKeys ) ;
var eventDrags = this . splitEventDrag ( props . eventDrag ) ;
var eventResizes = this . splitEventResize ( props . eventResize ) ;
var splitProps = { } ;
this . eventUiBuilders = mapHash ( keyInfos , function ( info , key ) {
return _this . eventUiBuilders [ key ] || memoize ( buildEventUiForKey ) ;
} ) ;
for ( var key in keyInfos ) {
var keyInfo = keyInfos [ key ] ;
var eventStore = eventStores [ key ] || EMPTY _EVENT _STORE ;
var buildEventUi = this . eventUiBuilders [ key ] ;
splitProps [ key ] = {
businessHours : keyInfo . businessHours || props . businessHours ,
dateSelection : dateSelections [ key ] || null ,
eventStore : eventStore ,
eventUiBases : buildEventUi ( props . eventUiBases [ '' ] , keyInfo . ui , individualUi [ key ] ) ,
eventSelection : eventStore . instances [ props . eventSelection ] ? props . eventSelection : '' ,
eventDrag : eventDrags [ key ] || null ,
eventResize : eventResizes [ key ] || null
} ;
}
return splitProps ;
} ;
Splitter . prototype . _splitDateSpan = function ( dateSpan ) {
var dateSpans = { } ;
if ( dateSpan ) {
var keys = this . getKeysForDateSpan ( dateSpan ) ;
for ( var _i = 0 , keys _1 = keys ; _i < keys _1 . length ; _i ++ ) {
var key = keys _1 [ _i ] ;
dateSpans [ key ] = dateSpan ;
}
}
return dateSpans ;
} ;
Splitter . prototype . _getKeysForEventDefs = function ( eventStore ) {
var _this = this ;
return mapHash ( eventStore . defs , function ( eventDef ) {
return _this . getKeysForEventDef ( eventDef ) ;
} ) ;
} ;
Splitter . prototype . _splitEventStore = function ( eventStore , defKeys ) {
var defs = eventStore . defs , instances = eventStore . instances ;
var splitStores = { } ;
for ( var defId in defs ) {
for ( var _i = 0 , _a = defKeys [ defId ] ; _i < _a . length ; _i ++ ) {
var key = _a [ _i ] ;
if ( ! splitStores [ key ] ) {
splitStores [ key ] = createEmptyEventStore ( ) ;
}
splitStores [ key ] . defs [ defId ] = defs [ defId ] ;
}
}
for ( var instanceId in instances ) {
var instance = instances [ instanceId ] ;
for ( var _b = 0 , _c = defKeys [ instance . defId ] ; _b < _c . length ; _b ++ ) {
var key = _c [ _b ] ;
if ( splitStores [ key ] ) { // must have already been created
splitStores [ key ] . instances [ instanceId ] = instance ;
}
}
}
return splitStores ;
} ;
Splitter . prototype . _splitIndividualUi = function ( eventUiBases , defKeys ) {
var splitHashes = { } ;
for ( var defId in eventUiBases ) {
if ( defId ) { // not the '' key
for ( var _i = 0 , _a = defKeys [ defId ] ; _i < _a . length ; _i ++ ) {
var key = _a [ _i ] ;
if ( ! splitHashes [ key ] ) {
splitHashes [ key ] = { } ;
}
splitHashes [ key ] [ defId ] = eventUiBases [ defId ] ;
}
}
}
return splitHashes ;
} ;
Splitter . prototype . _splitInteraction = function ( interaction ) {
var splitStates = { } ;
if ( interaction ) {
var affectedStores _1 = this . _splitEventStore ( interaction . affectedEvents , this . _getKeysForEventDefs ( interaction . affectedEvents ) // can't use cached. might be events from other calendar
) ;
// can't rely on defKeys because event data is mutated
var mutatedKeysByDefId = this . _getKeysForEventDefs ( interaction . mutatedEvents ) ;
var mutatedStores _1 = this . _splitEventStore ( interaction . mutatedEvents , mutatedKeysByDefId ) ;
var populate = function ( key ) {
if ( ! splitStates [ key ] ) {
splitStates [ key ] = {
affectedEvents : affectedStores _1 [ key ] || EMPTY _EVENT _STORE ,
mutatedEvents : mutatedStores _1 [ key ] || EMPTY _EVENT _STORE ,
isEvent : interaction . isEvent ,
origSeg : interaction . origSeg
} ;
}
} ;
for ( var key in affectedStores _1 ) {
populate ( key ) ;
}
for ( var key in mutatedStores _1 ) {
populate ( key ) ;
}
}
return splitStates ;
} ;
return Splitter ;
} ( ) ) ;
function buildEventUiForKey ( allUi , eventUiForKey , individualUi ) {
var baseParts = [ ] ;
if ( allUi ) {
baseParts . push ( allUi ) ;
}
if ( eventUiForKey ) {
baseParts . push ( eventUiForKey ) ;
}
var stuff = {
'' : combineEventUis ( baseParts )
} ;
if ( individualUi ) {
_ _assign ( stuff , individualUi ) ;
}
return stuff ;
}
// Generates HTML for an anchor to another view into the calendar.
// Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings.
// `gotoOptions` can either be a DateMarker, or an object with the form:
// { date, type, forceOff }
// `type` is a view-type like "day" or "week". default value is "day".
// `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
2020-04-01 22:52:43 +00:00
function buildGotoAnchorHtml ( allOptions , dateEnv , gotoOptions , attrs , innerHtml ) {
2019-08-28 10:59:33 +00:00
var date ;
var type ;
var forceOff ;
var finalOptions ;
if ( gotoOptions instanceof Date ) {
date = gotoOptions ; // a single date-like input
}
else {
date = gotoOptions . date ;
type = gotoOptions . type ;
forceOff = gotoOptions . forceOff ;
}
finalOptions = {
date : dateEnv . formatIso ( date , { omitTime : true } ) ,
type : type || 'day'
} ;
if ( typeof attrs === 'string' ) {
innerHtml = attrs ;
attrs = null ;
}
attrs = attrs ? ' ' + attrsToStr ( attrs ) : '' ; // will have a leading space
innerHtml = innerHtml || '' ;
2020-04-01 22:52:43 +00:00
if ( ! forceOff && allOptions . navLinks ) {
2019-08-28 10:59:33 +00:00
return '<a' + attrs +
' data-goto="' + htmlEscape ( JSON . stringify ( finalOptions ) ) + '">' +
innerHtml +
'</a>' ;
}
else {
return '<span' + attrs + '>' +
innerHtml +
'</span>' ;
}
}
2020-04-01 22:52:43 +00:00
function getAllDayHtml ( allOptions ) {
return allOptions . allDayHtml || htmlEscape ( allOptions . allDayText ) ;
2019-08-28 10:59:33 +00:00
}
// Computes HTML classNames for a single-day element
function getDayClasses ( date , dateProfile , context , noThemeHighlight ) {
2020-04-01 22:52:43 +00:00
var calendar = context . calendar , options = context . options , theme = context . theme , dateEnv = context . dateEnv ;
2019-08-28 10:59:33 +00:00
var classes = [ ] ;
var todayStart ;
var todayEnd ;
if ( ! rangeContainsMarker ( dateProfile . activeRange , date ) ) {
classes . push ( 'fc-disabled-day' ) ;
}
else {
classes . push ( 'fc-' + DAY _IDS [ date . getUTCDay ( ) ] ) ;
2020-04-01 22:52:43 +00:00
if ( options . monthMode &&
2019-08-28 10:59:33 +00:00
dateEnv . getMonth ( date ) !== dateEnv . getMonth ( dateProfile . currentRange . start ) ) {
classes . push ( 'fc-other-month' ) ;
}
todayStart = startOfDay ( calendar . getNow ( ) ) ;
todayEnd = addDays ( todayStart , 1 ) ;
if ( date < todayStart ) {
classes . push ( 'fc-past' ) ;
}
else if ( date >= todayEnd ) {
classes . push ( 'fc-future' ) ;
}
else {
classes . push ( 'fc-today' ) ;
if ( noThemeHighlight !== true ) {
classes . push ( theme . getClass ( 'today' ) ) ;
}
}
}
return classes ;
}
// given a function that resolves a result asynchronously.
// the function can either call passed-in success and failure callbacks,
// or it can return a promise.
// if you need to pass additional params to func, bind them first.
function unpromisify ( func , success , failure ) {
// guard against success/failure callbacks being called more than once
// and guard against a promise AND callback being used together.
var isResolved = false ;
var wrappedSuccess = function ( ) {
if ( ! isResolved ) {
isResolved = true ;
success . apply ( this , arguments ) ;
}
} ;
var wrappedFailure = function ( ) {
if ( ! isResolved ) {
isResolved = true ;
if ( failure ) {
failure . apply ( this , arguments ) ;
}
}
} ;
var res = func ( wrappedSuccess , wrappedFailure ) ;
if ( res && typeof res . then === 'function' ) {
res . then ( wrappedSuccess , wrappedFailure ) ;
}
}
var Mixin = /** @class */ ( function ( ) {
function Mixin ( ) {
}
// mix into a CLASS
Mixin . mixInto = function ( destClass ) {
this . mixIntoObj ( destClass . prototype ) ;
} ;
// mix into ANY object
Mixin . mixIntoObj = function ( destObj ) {
var _this = this ;
Object . getOwnPropertyNames ( this . prototype ) . forEach ( function ( name ) {
if ( ! destObj [ name ] ) { // if destination doesn't already define it
destObj [ name ] = _this . prototype [ name ] ;
}
} ) ;
} ;
/ *
will override existing methods
TODO : remove ! not used anymore
* /
Mixin . mixOver = function ( destClass ) {
var _this = this ;
Object . getOwnPropertyNames ( this . prototype ) . forEach ( function ( name ) {
destClass . prototype [ name ] = _this . prototype [ name ] ;
} ) ;
} ;
return Mixin ;
} ( ) ) ;
/ *
USAGE :
import { default as EmitterMixin , EmitterInterface } from './EmitterMixin'
in class :
on : EmitterInterface [ 'on' ]
one : EmitterInterface [ 'one' ]
off : EmitterInterface [ 'off' ]
trigger : EmitterInterface [ 'trigger' ]
triggerWith : EmitterInterface [ 'triggerWith' ]
hasHandlers : EmitterInterface [ 'hasHandlers' ]
after class :
EmitterMixin . mixInto ( TheClass )
* /
var EmitterMixin = /** @class */ ( function ( _super ) {
_ _extends ( EmitterMixin , _super ) ;
function EmitterMixin ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
EmitterMixin . prototype . on = function ( type , handler ) {
addToHash ( this . _handlers || ( this . _handlers = { } ) , type , handler ) ;
return this ; // for chaining
} ;
// todo: add comments
EmitterMixin . prototype . one = function ( type , handler ) {
addToHash ( this . _oneHandlers || ( this . _oneHandlers = { } ) , type , handler ) ;
return this ; // for chaining
} ;
EmitterMixin . prototype . off = function ( type , handler ) {
if ( this . _handlers ) {
removeFromHash ( this . _handlers , type , handler ) ;
}
if ( this . _oneHandlers ) {
removeFromHash ( this . _oneHandlers , type , handler ) ;
}
return this ; // for chaining
} ;
EmitterMixin . prototype . trigger = function ( type ) {
var args = [ ] ;
for ( var _i = 1 ; _i < arguments . length ; _i ++ ) {
args [ _i - 1 ] = arguments [ _i ] ;
}
this . triggerWith ( type , this , args ) ;
return this ; // for chaining
} ;
EmitterMixin . prototype . triggerWith = function ( type , context , args ) {
if ( this . _handlers ) {
applyAll ( this . _handlers [ type ] , context , args ) ;
}
if ( this . _oneHandlers ) {
applyAll ( this . _oneHandlers [ type ] , context , args ) ;
delete this . _oneHandlers [ type ] ; // will never fire again
}
return this ; // for chaining
} ;
EmitterMixin . prototype . hasHandlers = function ( type ) {
return ( this . _handlers && this . _handlers [ type ] && this . _handlers [ type ] . length ) ||
( this . _oneHandlers && this . _oneHandlers [ type ] && this . _oneHandlers [ type ] . length ) ;
} ;
return EmitterMixin ;
} ( Mixin ) ) ;
function addToHash ( hash , type , handler ) {
( hash [ type ] || ( hash [ type ] = [ ] ) )
. push ( handler ) ;
}
function removeFromHash ( hash , type , handler ) {
if ( handler ) {
if ( hash [ type ] ) {
hash [ type ] = hash [ type ] . filter ( function ( func ) {
return func !== handler ;
} ) ;
}
}
else {
delete hash [ type ] ; // remove all handler funcs for this type
}
}
/ *
Records offset information for a set of elements , relative to an origin element .
Can record the left / right OR the top / bottom OR both .
Provides methods for querying the cache by position .
* /
var PositionCache = /** @class */ ( function ( ) {
function PositionCache ( originEl , els , isHorizontal , isVertical ) {
this . originEl = originEl ;
this . els = els ;
this . isHorizontal = isHorizontal ;
this . isVertical = isVertical ;
}
// Queries the els for coordinates and stores them.
// Call this method before using and of the get* methods below.
PositionCache . prototype . build = function ( ) {
var originEl = this . originEl ;
var originClientRect = this . originClientRect =
originEl . getBoundingClientRect ( ) ; // relative to viewport top-left
if ( this . isHorizontal ) {
this . buildElHorizontals ( originClientRect . left ) ;
}
if ( this . isVertical ) {
this . buildElVerticals ( originClientRect . top ) ;
}
} ;
// Populates the left/right internal coordinate arrays
PositionCache . prototype . buildElHorizontals = function ( originClientLeft ) {
var lefts = [ ] ;
var rights = [ ] ;
for ( var _i = 0 , _a = this . els ; _i < _a . length ; _i ++ ) {
var el = _a [ _i ] ;
var rect = el . getBoundingClientRect ( ) ;
lefts . push ( rect . left - originClientLeft ) ;
rights . push ( rect . right - originClientLeft ) ;
}
this . lefts = lefts ;
this . rights = rights ;
} ;
// Populates the top/bottom internal coordinate arrays
PositionCache . prototype . buildElVerticals = function ( originClientTop ) {
var tops = [ ] ;
var bottoms = [ ] ;
for ( var _i = 0 , _a = this . els ; _i < _a . length ; _i ++ ) {
var el = _a [ _i ] ;
var rect = el . getBoundingClientRect ( ) ;
tops . push ( rect . top - originClientTop ) ;
bottoms . push ( rect . bottom - originClientTop ) ;
}
this . tops = tops ;
this . bottoms = bottoms ;
} ;
// Given a left offset (from document left), returns the index of the el that it horizontally intersects.
// If no intersection is made, returns undefined.
PositionCache . prototype . leftToIndex = function ( leftPosition ) {
var lefts = this . lefts ;
var rights = this . rights ;
var len = lefts . length ;
var i ;
for ( i = 0 ; i < len ; i ++ ) {
if ( leftPosition >= lefts [ i ] && leftPosition < rights [ i ] ) {
return i ;
}
}
} ;
// Given a top offset (from document top), returns the index of the el that it vertically intersects.
// If no intersection is made, returns undefined.
PositionCache . prototype . topToIndex = function ( topPosition ) {
var tops = this . tops ;
var bottoms = this . bottoms ;
var len = tops . length ;
var i ;
for ( i = 0 ; i < len ; i ++ ) {
if ( topPosition >= tops [ i ] && topPosition < bottoms [ i ] ) {
return i ;
}
}
} ;
// Gets the width of the element at the given index
PositionCache . prototype . getWidth = function ( leftIndex ) {
return this . rights [ leftIndex ] - this . lefts [ leftIndex ] ;
} ;
// Gets the height of the element at the given index
PositionCache . prototype . getHeight = function ( topIndex ) {
return this . bottoms [ topIndex ] - this . tops [ topIndex ] ;
} ;
return PositionCache ;
} ( ) ) ;
/ *
An object for getting / setting scroll - related information for an element .
Internally , this is done very differently for window versus DOM element ,
so this object serves as a common interface .
* /
var ScrollController = /** @class */ ( function ( ) {
function ScrollController ( ) {
}
ScrollController . prototype . getMaxScrollTop = function ( ) {
return this . getScrollHeight ( ) - this . getClientHeight ( ) ;
} ;
ScrollController . prototype . getMaxScrollLeft = function ( ) {
return this . getScrollWidth ( ) - this . getClientWidth ( ) ;
} ;
ScrollController . prototype . canScrollVertically = function ( ) {
return this . getMaxScrollTop ( ) > 0 ;
} ;
ScrollController . prototype . canScrollHorizontally = function ( ) {
return this . getMaxScrollLeft ( ) > 0 ;
} ;
ScrollController . prototype . canScrollUp = function ( ) {
return this . getScrollTop ( ) > 0 ;
} ;
ScrollController . prototype . canScrollDown = function ( ) {
return this . getScrollTop ( ) < this . getMaxScrollTop ( ) ;
} ;
ScrollController . prototype . canScrollLeft = function ( ) {
return this . getScrollLeft ( ) > 0 ;
} ;
ScrollController . prototype . canScrollRight = function ( ) {
return this . getScrollLeft ( ) < this . getMaxScrollLeft ( ) ;
} ;
return ScrollController ;
} ( ) ) ;
var ElementScrollController = /** @class */ ( function ( _super ) {
_ _extends ( ElementScrollController , _super ) ;
function ElementScrollController ( el ) {
var _this = _super . call ( this ) || this ;
_this . el = el ;
return _this ;
}
ElementScrollController . prototype . getScrollTop = function ( ) {
return this . el . scrollTop ;
} ;
ElementScrollController . prototype . getScrollLeft = function ( ) {
return this . el . scrollLeft ;
} ;
ElementScrollController . prototype . setScrollTop = function ( top ) {
this . el . scrollTop = top ;
} ;
ElementScrollController . prototype . setScrollLeft = function ( left ) {
this . el . scrollLeft = left ;
} ;
ElementScrollController . prototype . getScrollWidth = function ( ) {
return this . el . scrollWidth ;
} ;
ElementScrollController . prototype . getScrollHeight = function ( ) {
return this . el . scrollHeight ;
} ;
ElementScrollController . prototype . getClientHeight = function ( ) {
return this . el . clientHeight ;
} ;
ElementScrollController . prototype . getClientWidth = function ( ) {
return this . el . clientWidth ;
} ;
return ElementScrollController ;
} ( ScrollController ) ) ;
var WindowScrollController = /** @class */ ( function ( _super ) {
_ _extends ( WindowScrollController , _super ) ;
function WindowScrollController ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
WindowScrollController . prototype . getScrollTop = function ( ) {
return window . pageYOffset ;
} ;
WindowScrollController . prototype . getScrollLeft = function ( ) {
return window . pageXOffset ;
} ;
WindowScrollController . prototype . setScrollTop = function ( n ) {
window . scroll ( window . pageXOffset , n ) ;
} ;
WindowScrollController . prototype . setScrollLeft = function ( n ) {
window . scroll ( n , window . pageYOffset ) ;
} ;
WindowScrollController . prototype . getScrollWidth = function ( ) {
return document . documentElement . scrollWidth ;
} ;
WindowScrollController . prototype . getScrollHeight = function ( ) {
return document . documentElement . scrollHeight ;
} ;
WindowScrollController . prototype . getClientHeight = function ( ) {
return document . documentElement . clientHeight ;
} ;
WindowScrollController . prototype . getClientWidth = function ( ) {
return document . documentElement . clientWidth ;
} ;
return WindowScrollController ;
} ( ScrollController ) ) ;
/ *
Embodies a div that has potential scrollbars
* /
var ScrollComponent = /** @class */ ( function ( _super ) {
_ _extends ( ScrollComponent , _super ) ;
function ScrollComponent ( overflowX , overflowY ) {
var _this = _super . call ( this , createElement ( 'div' , {
className : 'fc-scroller'
} ) ) || this ;
_this . overflowX = overflowX ;
_this . overflowY = overflowY ;
_this . applyOverflow ( ) ;
return _this ;
}
// sets to natural height, unlocks overflow
ScrollComponent . prototype . clear = function ( ) {
this . setHeight ( 'auto' ) ;
this . applyOverflow ( ) ;
} ;
ScrollComponent . prototype . destroy = function ( ) {
removeElement ( this . el ) ;
} ;
// Overflow
// -----------------------------------------------------------------------------------------------------------------
ScrollComponent . prototype . applyOverflow = function ( ) {
applyStyle ( this . el , {
overflowX : this . overflowX ,
overflowY : this . overflowY
} ) ;
} ;
// Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.
// Useful for preserving scrollbar widths regardless of future resizes.
// Can pass in scrollbarWidths for optimization.
ScrollComponent . prototype . lockOverflow = function ( scrollbarWidths ) {
var overflowX = this . overflowX ;
var overflowY = this . overflowY ;
scrollbarWidths = scrollbarWidths || this . getScrollbarWidths ( ) ;
if ( overflowX === 'auto' ) {
overflowX = ( scrollbarWidths . bottom || // horizontal scrollbars?
this . canScrollHorizontally ( ) // OR scrolling pane with massless scrollbars?
) ? 'scroll' : 'hidden' ;
}
if ( overflowY === 'auto' ) {
overflowY = ( scrollbarWidths . left || scrollbarWidths . right || // horizontal scrollbars?
this . canScrollVertically ( ) // OR scrolling pane with massless scrollbars?
) ? 'scroll' : 'hidden' ;
}
applyStyle ( this . el , { overflowX : overflowX , overflowY : overflowY } ) ;
} ;
ScrollComponent . prototype . setHeight = function ( height ) {
applyStyleProp ( this . el , 'height' , height ) ;
} ;
ScrollComponent . prototype . getScrollbarWidths = function ( ) {
var edges = computeEdges ( this . el ) ;
return {
left : edges . scrollbarLeft ,
right : edges . scrollbarRight ,
bottom : edges . scrollbarBottom
} ;
} ;
return ScrollComponent ;
} ( ElementScrollController ) ) ;
var Theme = /** @class */ ( function ( ) {
function Theme ( calendarOptions ) {
this . calendarOptions = calendarOptions ;
this . processIconOverride ( ) ;
}
Theme . prototype . processIconOverride = function ( ) {
if ( this . iconOverrideOption ) {
this . setIconOverride ( this . calendarOptions [ this . iconOverrideOption ] ) ;
}
} ;
Theme . prototype . setIconOverride = function ( iconOverrideHash ) {
var iconClassesCopy ;
var buttonName ;
if ( typeof iconOverrideHash === 'object' && iconOverrideHash ) { // non-null object
iconClassesCopy = _ _assign ( { } , this . iconClasses ) ;
for ( buttonName in iconOverrideHash ) {
iconClassesCopy [ buttonName ] = this . applyIconOverridePrefix ( iconOverrideHash [ buttonName ] ) ;
}
this . iconClasses = iconClassesCopy ;
}
else if ( iconOverrideHash === false ) {
this . iconClasses = { } ;
}
} ;
Theme . prototype . applyIconOverridePrefix = function ( className ) {
var prefix = this . iconOverridePrefix ;
if ( prefix && className . indexOf ( prefix ) !== 0 ) { // if not already present
className = prefix + className ;
}
return className ;
} ;
Theme . prototype . getClass = function ( key ) {
return this . classes [ key ] || '' ;
} ;
Theme . prototype . getIconClass = function ( buttonName ) {
var className = this . iconClasses [ buttonName ] ;
if ( className ) {
return this . baseIconClass + ' ' + className ;
}
return '' ;
} ;
Theme . prototype . getCustomButtonIconClass = function ( customButtonProps ) {
var className ;
if ( this . iconOverrideCustomButtonOption ) {
className = customButtonProps [ this . iconOverrideCustomButtonOption ] ;
if ( className ) {
return this . baseIconClass + ' ' + this . applyIconOverridePrefix ( className ) ;
}
}
return '' ;
} ;
return Theme ;
} ( ) ) ;
Theme . prototype . classes = { } ;
Theme . prototype . iconClasses = { } ;
Theme . prototype . baseIconClass = '' ;
Theme . prototype . iconOverridePrefix = '' ;
var guid = 0 ;
2020-04-01 22:52:43 +00:00
var ComponentContext = /** @class */ ( function ( ) {
function ComponentContext ( calendar , theme , dateEnv , options , view ) {
this . calendar = calendar ;
this . theme = theme ;
this . dateEnv = dateEnv ;
this . options = options ;
this . view = view ;
this . isRtl = options . dir === 'rtl' ;
this . eventOrderSpecs = parseFieldSpecs ( options . eventOrder ) ;
this . nextDayThreshold = createDuration ( options . nextDayThreshold ) ;
}
ComponentContext . prototype . extend = function ( options , view ) {
return new ComponentContext ( this . calendar , this . theme , this . dateEnv , options || this . options , view || this . view ) ;
} ;
return ComponentContext ;
} ( ) ) ;
2019-08-28 10:59:33 +00:00
var Component = /** @class */ ( function ( ) {
2020-04-01 22:52:43 +00:00
function Component ( ) {
2020-06-01 11:05:25 +00:00
this . everRendered = false ;
2019-08-28 10:59:33 +00:00
this . uid = String ( guid ++ ) ;
}
Component . addEqualityFuncs = function ( newFuncs ) {
this . prototype . equalityFuncs = _ _assign ( { } , this . prototype . equalityFuncs , newFuncs ) ;
} ;
2020-04-01 22:52:43 +00:00
Component . prototype . receiveProps = function ( props , context ) {
2020-06-01 11:05:25 +00:00
this . receiveContext ( context ) ;
2019-08-28 10:59:33 +00:00
var _a = recycleProps ( this . props || { } , props , this . equalityFuncs ) , anyChanges = _a . anyChanges , comboProps = _a . comboProps ;
this . props = comboProps ;
if ( anyChanges ) {
2020-06-01 11:05:25 +00:00
if ( this . everRendered ) {
2020-04-01 22:52:43 +00:00
this . beforeUpdate ( ) ;
}
this . render ( comboProps , context ) ;
2020-06-01 11:05:25 +00:00
if ( this . everRendered ) {
2020-04-01 22:52:43 +00:00
this . afterUpdate ( ) ;
}
2019-08-28 10:59:33 +00:00
}
2020-06-01 11:05:25 +00:00
this . everRendered = true ;
} ;
Component . prototype . receiveContext = function ( context ) {
var oldContext = this . context ;
this . context = context ;
if ( ! oldContext ) {
this . firstContext ( context ) ;
}
2019-08-28 10:59:33 +00:00
} ;
2020-04-01 22:52:43 +00:00
Component . prototype . render = function ( props , context ) {
} ;
Component . prototype . firstContext = function ( context ) {
} ;
Component . prototype . beforeUpdate = function ( ) {
} ;
Component . prototype . afterUpdate = function ( ) {
2019-08-28 10:59:33 +00:00
} ;
// after destroy is called, this component won't ever be used again
Component . prototype . destroy = function ( ) {
} ;
return Component ;
} ( ) ) ;
Component . prototype . equalityFuncs = { } ;
/ *
Reuses old values when equal . If anything is unequal , returns newProps as - is .
Great for PureComponent , but won 't be feasible with React, so just eliminate and use React' s DOM diffing .
* /
function recycleProps ( oldProps , newProps , equalityFuncs ) {
var comboProps = { } ; // some old, some new
var anyChanges = false ;
for ( var key in newProps ) {
if ( key in oldProps && ( oldProps [ key ] === newProps [ key ] ||
( equalityFuncs [ key ] && equalityFuncs [ key ] ( oldProps [ key ] , newProps [ key ] ) ) ) ) {
// equal to old? use old prop
comboProps [ key ] = oldProps [ key ] ;
}
else {
comboProps [ key ] = newProps [ key ] ;
anyChanges = true ;
}
}
for ( var key in oldProps ) {
if ( ! ( key in newProps ) ) {
anyChanges = true ;
break ;
}
}
return { anyChanges : anyChanges , comboProps : comboProps } ;
}
/ *
PURPOSES :
- hook up to fg , fill , and mirror renderers
- interface for dragging and hits
* /
var DateComponent = /** @class */ ( function ( _super ) {
_ _extends ( DateComponent , _super ) ;
2020-04-01 22:52:43 +00:00
function DateComponent ( el ) {
var _this = _super . call ( this ) || this ;
2019-08-28 10:59:33 +00:00
_this . el = el ;
return _this ;
}
DateComponent . prototype . destroy = function ( ) {
_super . prototype . destroy . call ( this ) ;
removeElement ( this . el ) ;
} ;
// Hit System
// -----------------------------------------------------------------------------------------------------------------
DateComponent . prototype . buildPositionCaches = function ( ) {
} ;
DateComponent . prototype . queryHit = function ( positionLeft , positionTop , elWidth , elHeight ) {
return null ; // this should be abstract
} ;
// Validation
// -----------------------------------------------------------------------------------------------------------------
DateComponent . prototype . isInteractionValid = function ( interaction ) {
2020-04-01 22:52:43 +00:00
var calendar = this . context . calendar ;
2019-08-28 10:59:33 +00:00
var dateProfile = this . props . dateProfile ; // HACK
var instances = interaction . mutatedEvents . instances ;
if ( dateProfile ) { // HACK for DayTile
for ( var instanceId in instances ) {
if ( ! rangeContainsRange ( dateProfile . validRange , instances [ instanceId ] . range ) ) {
return false ;
}
}
}
return isInteractionValid ( interaction , calendar ) ;
} ;
DateComponent . prototype . isDateSelectionValid = function ( selection ) {
2020-04-01 22:52:43 +00:00
var calendar = this . context . calendar ;
2019-08-28 10:59:33 +00:00
var dateProfile = this . props . dateProfile ; // HACK
if ( dateProfile && // HACK for DayTile
! rangeContainsRange ( dateProfile . validRange , selection . range ) ) {
return false ;
}
2020-04-01 22:52:43 +00:00
return isDateSelectionValid ( selection , calendar ) ;
2019-08-28 10:59:33 +00:00
} ;
// Pointer Interaction Utils
// -----------------------------------------------------------------------------------------------------------------
DateComponent . prototype . isValidSegDownEl = function ( el ) {
return ! this . props . eventDrag && // HACK
! this . props . eventResize && // HACK
! elementClosest ( el , '.fc-mirror' ) &&
( this . isPopover ( ) || ! this . isInPopover ( el ) ) ;
// ^above line ensures we don't detect a seg interaction within a nested component.
// it's a HACK because it only supports a popover as the nested component.
} ;
DateComponent . prototype . isValidDateDownEl = function ( el ) {
var segEl = elementClosest ( el , this . fgSegSelector ) ;
return ( ! segEl || segEl . classList . contains ( 'fc-mirror' ) ) &&
! elementClosest ( el , '.fc-more' ) && // a "more.." link
! elementClosest ( el , 'a[data-goto]' ) && // a clickable nav link
! this . isInPopover ( el ) ;
} ;
DateComponent . prototype . isPopover = function ( ) {
return this . el . classList . contains ( 'fc-popover' ) ;
} ;
DateComponent . prototype . isInPopover = function ( el ) {
return Boolean ( elementClosest ( el , '.fc-popover' ) ) ;
} ;
return DateComponent ;
} ( Component ) ) ;
DateComponent . prototype . fgSegSelector = '.fc-event-container > *' ;
DateComponent . prototype . bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)' ;
var uid$1 = 0 ;
function createPlugin ( input ) {
return {
id : String ( uid$1 ++ ) ,
deps : input . deps || [ ] ,
reducers : input . reducers || [ ] ,
eventDefParsers : input . eventDefParsers || [ ] ,
isDraggableTransformers : input . isDraggableTransformers || [ ] ,
eventDragMutationMassagers : input . eventDragMutationMassagers || [ ] ,
eventDefMutationAppliers : input . eventDefMutationAppliers || [ ] ,
dateSelectionTransformers : input . dateSelectionTransformers || [ ] ,
datePointTransforms : input . datePointTransforms || [ ] ,
dateSpanTransforms : input . dateSpanTransforms || [ ] ,
views : input . views || { } ,
viewPropsTransformers : input . viewPropsTransformers || [ ] ,
isPropsValid : input . isPropsValid || null ,
externalDefTransforms : input . externalDefTransforms || [ ] ,
eventResizeJoinTransforms : input . eventResizeJoinTransforms || [ ] ,
viewContainerModifiers : input . viewContainerModifiers || [ ] ,
eventDropTransformers : input . eventDropTransformers || [ ] ,
componentInteractions : input . componentInteractions || [ ] ,
calendarInteractions : input . calendarInteractions || [ ] ,
themeClasses : input . themeClasses || { } ,
eventSourceDefs : input . eventSourceDefs || [ ] ,
cmdFormatter : input . cmdFormatter ,
recurringTypes : input . recurringTypes || [ ] ,
namedTimeZonedImpl : input . namedTimeZonedImpl ,
defaultView : input . defaultView || '' ,
elementDraggingImpl : input . elementDraggingImpl ,
optionChangeHandlers : input . optionChangeHandlers || { }
} ;
}
var PluginSystem = /** @class */ ( function ( ) {
function PluginSystem ( ) {
this . hooks = {
reducers : [ ] ,
eventDefParsers : [ ] ,
isDraggableTransformers : [ ] ,
eventDragMutationMassagers : [ ] ,
eventDefMutationAppliers : [ ] ,
dateSelectionTransformers : [ ] ,
datePointTransforms : [ ] ,
dateSpanTransforms : [ ] ,
views : { } ,
viewPropsTransformers : [ ] ,
isPropsValid : null ,
externalDefTransforms : [ ] ,
eventResizeJoinTransforms : [ ] ,
viewContainerModifiers : [ ] ,
eventDropTransformers : [ ] ,
componentInteractions : [ ] ,
calendarInteractions : [ ] ,
themeClasses : { } ,
eventSourceDefs : [ ] ,
cmdFormatter : null ,
recurringTypes : [ ] ,
namedTimeZonedImpl : null ,
defaultView : '' ,
elementDraggingImpl : null ,
optionChangeHandlers : { }
} ;
this . addedHash = { } ;
}
PluginSystem . prototype . add = function ( plugin ) {
if ( ! this . addedHash [ plugin . id ] ) {
this . addedHash [ plugin . id ] = true ;
for ( var _i = 0 , _a = plugin . deps ; _i < _a . length ; _i ++ ) {
var dep = _a [ _i ] ;
this . add ( dep ) ;
}
this . hooks = combineHooks ( this . hooks , plugin ) ;
}
} ;
return PluginSystem ;
} ( ) ) ;
function combineHooks ( hooks0 , hooks1 ) {
return {
reducers : hooks0 . reducers . concat ( hooks1 . reducers ) ,
eventDefParsers : hooks0 . eventDefParsers . concat ( hooks1 . eventDefParsers ) ,
isDraggableTransformers : hooks0 . isDraggableTransformers . concat ( hooks1 . isDraggableTransformers ) ,
eventDragMutationMassagers : hooks0 . eventDragMutationMassagers . concat ( hooks1 . eventDragMutationMassagers ) ,
eventDefMutationAppliers : hooks0 . eventDefMutationAppliers . concat ( hooks1 . eventDefMutationAppliers ) ,
dateSelectionTransformers : hooks0 . dateSelectionTransformers . concat ( hooks1 . dateSelectionTransformers ) ,
datePointTransforms : hooks0 . datePointTransforms . concat ( hooks1 . datePointTransforms ) ,
dateSpanTransforms : hooks0 . dateSpanTransforms . concat ( hooks1 . dateSpanTransforms ) ,
views : _ _assign ( { } , hooks0 . views , hooks1 . views ) ,
viewPropsTransformers : hooks0 . viewPropsTransformers . concat ( hooks1 . viewPropsTransformers ) ,
isPropsValid : hooks1 . isPropsValid || hooks0 . isPropsValid ,
externalDefTransforms : hooks0 . externalDefTransforms . concat ( hooks1 . externalDefTransforms ) ,
eventResizeJoinTransforms : hooks0 . eventResizeJoinTransforms . concat ( hooks1 . eventResizeJoinTransforms ) ,
viewContainerModifiers : hooks0 . viewContainerModifiers . concat ( hooks1 . viewContainerModifiers ) ,
eventDropTransformers : hooks0 . eventDropTransformers . concat ( hooks1 . eventDropTransformers ) ,
calendarInteractions : hooks0 . calendarInteractions . concat ( hooks1 . calendarInteractions ) ,
componentInteractions : hooks0 . componentInteractions . concat ( hooks1 . componentInteractions ) ,
themeClasses : _ _assign ( { } , hooks0 . themeClasses , hooks1 . themeClasses ) ,
eventSourceDefs : hooks0 . eventSourceDefs . concat ( hooks1 . eventSourceDefs ) ,
cmdFormatter : hooks1 . cmdFormatter || hooks0 . cmdFormatter ,
recurringTypes : hooks0 . recurringTypes . concat ( hooks1 . recurringTypes ) ,
namedTimeZonedImpl : hooks1 . namedTimeZonedImpl || hooks0 . namedTimeZonedImpl ,
defaultView : hooks0 . defaultView || hooks1 . defaultView ,
elementDraggingImpl : hooks0 . elementDraggingImpl || hooks1 . elementDraggingImpl ,
optionChangeHandlers : _ _assign ( { } , hooks0 . optionChangeHandlers , hooks1 . optionChangeHandlers )
} ;
}
var eventSourceDef = {
ignoreRange : true ,
parseMeta : function ( raw ) {
if ( Array . isArray ( raw ) ) { // short form
return raw ;
}
else if ( Array . isArray ( raw . events ) ) {
return raw . events ;
}
return null ;
} ,
fetch : function ( arg , success ) {
success ( {
rawEvents : arg . eventSource . meta
} ) ;
}
} ;
var ArrayEventSourcePlugin = createPlugin ( {
eventSourceDefs : [ eventSourceDef ]
} ) ;
var eventSourceDef$1 = {
parseMeta : function ( raw ) {
if ( typeof raw === 'function' ) { // short form
return raw ;
}
else if ( typeof raw . events === 'function' ) {
return raw . events ;
}
return null ;
} ,
fetch : function ( arg , success , failure ) {
var dateEnv = arg . calendar . dateEnv ;
var func = arg . eventSource . meta ;
unpromisify ( func . bind ( null , {
start : dateEnv . toDate ( arg . range . start ) ,
end : dateEnv . toDate ( arg . range . end ) ,
startStr : dateEnv . formatIso ( arg . range . start ) ,
endStr : dateEnv . formatIso ( arg . range . end ) ,
timeZone : dateEnv . timeZone
} ) , function ( rawEvents ) {
success ( { rawEvents : rawEvents } ) ; // needs an object response
} , failure // send errorObj directly to failure callback
) ;
}
} ;
var FuncEventSourcePlugin = createPlugin ( {
eventSourceDefs : [ eventSourceDef$1 ]
} ) ;
function requestJson ( method , url , params , successCallback , failureCallback ) {
method = method . toUpperCase ( ) ;
var body = null ;
if ( method === 'GET' ) {
url = injectQueryStringParams ( url , params ) ;
}
else {
body = encodeParams ( params ) ;
}
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( method , url , true ) ;
if ( method !== 'GET' ) {
xhr . setRequestHeader ( 'Content-Type' , 'application/x-www-form-urlencoded' ) ;
}
xhr . onload = function ( ) {
if ( xhr . status >= 200 && xhr . status < 400 ) {
try {
var res = JSON . parse ( xhr . responseText ) ;
successCallback ( res , xhr ) ;
}
catch ( err ) {
failureCallback ( 'Failure parsing JSON' , xhr ) ;
}
}
else {
failureCallback ( 'Request failed' , xhr ) ;
}
} ;
xhr . onerror = function ( ) {
failureCallback ( 'Request failed' , xhr ) ;
} ;
xhr . send ( body ) ;
}
function injectQueryStringParams ( url , params ) {
return url +
( url . indexOf ( '?' ) === - 1 ? '?' : '&' ) +
encodeParams ( params ) ;
}
function encodeParams ( params ) {
var parts = [ ] ;
for ( var key in params ) {
parts . push ( encodeURIComponent ( key ) + '=' + encodeURIComponent ( params [ key ] ) ) ;
}
return parts . join ( '&' ) ;
}
var eventSourceDef$2 = {
parseMeta : function ( raw ) {
if ( typeof raw === 'string' ) { // short form
raw = { url : raw } ;
}
else if ( ! raw || typeof raw !== 'object' || ! raw . url ) {
return null ;
}
return {
url : raw . url ,
method : ( raw . method || 'GET' ) . toUpperCase ( ) ,
extraParams : raw . extraParams ,
startParam : raw . startParam ,
endParam : raw . endParam ,
timeZoneParam : raw . timeZoneParam
} ;
} ,
fetch : function ( arg , success , failure ) {
var meta = arg . eventSource . meta ;
var requestParams = buildRequestParams ( meta , arg . range , arg . calendar ) ;
requestJson ( meta . method , meta . url , requestParams , function ( rawEvents , xhr ) {
success ( { rawEvents : rawEvents , xhr : xhr } ) ;
} , function ( errorMessage , xhr ) {
failure ( { message : errorMessage , xhr : xhr } ) ;
} ) ;
}
} ;
var JsonFeedEventSourcePlugin = createPlugin ( {
eventSourceDefs : [ eventSourceDef$2 ]
} ) ;
function buildRequestParams ( meta , range , calendar ) {
var dateEnv = calendar . dateEnv ;
var startParam ;
var endParam ;
var timeZoneParam ;
var customRequestParams ;
var params = { } ;
startParam = meta . startParam ;
if ( startParam == null ) {
startParam = calendar . opt ( 'startParam' ) ;
}
endParam = meta . endParam ;
if ( endParam == null ) {
endParam = calendar . opt ( 'endParam' ) ;
}
timeZoneParam = meta . timeZoneParam ;
if ( timeZoneParam == null ) {
timeZoneParam = calendar . opt ( 'timeZoneParam' ) ;
}
// retrieve any outbound GET/POST data from the options
if ( typeof meta . extraParams === 'function' ) {
// supplied as a function that returns a key/value object
customRequestParams = meta . extraParams ( ) ;
}
else {
// probably supplied as a straight key/value object
customRequestParams = meta . extraParams || { } ;
}
_ _assign ( params , customRequestParams ) ;
params [ startParam ] = dateEnv . formatIso ( range . start ) ;
params [ endParam ] = dateEnv . formatIso ( range . end ) ;
if ( dateEnv . timeZone !== 'local' ) {
params [ timeZoneParam ] = dateEnv . timeZone ;
}
return params ;
}
var recurring = {
parse : function ( rawEvent , leftoverProps , dateEnv ) {
var createMarker = dateEnv . createMarker . bind ( dateEnv ) ;
var processors = {
daysOfWeek : null ,
startTime : createDuration ,
endTime : createDuration ,
startRecur : createMarker ,
endRecur : createMarker
} ;
var props = refineProps ( rawEvent , processors , { } , leftoverProps ) ;
var anyValid = false ;
for ( var propName in props ) {
if ( props [ propName ] != null ) {
anyValid = true ;
break ;
}
}
if ( anyValid ) {
var duration = null ;
if ( 'duration' in leftoverProps ) {
duration = createDuration ( leftoverProps . duration ) ;
delete leftoverProps . duration ;
}
if ( ! duration && props . startTime && props . endTime ) {
duration = subtractDurations ( props . endTime , props . startTime ) ;
}
return {
allDayGuess : Boolean ( ! props . startTime && ! props . endTime ) ,
duration : duration ,
typeData : props // doesn't need endTime anymore but oh well
} ;
}
return null ;
} ,
expand : function ( typeData , framingRange , dateEnv ) {
var clippedFramingRange = intersectRanges ( framingRange , { start : typeData . startRecur , end : typeData . endRecur } ) ;
if ( clippedFramingRange ) {
return expandRanges ( typeData . daysOfWeek , typeData . startTime , clippedFramingRange , dateEnv ) ;
}
else {
return [ ] ;
}
}
} ;
var SimpleRecurrencePlugin = createPlugin ( {
recurringTypes : [ recurring ]
} ) ;
function expandRanges ( daysOfWeek , startTime , framingRange , dateEnv ) {
var dowHash = daysOfWeek ? arrayToHash ( daysOfWeek ) : null ;
var dayMarker = startOfDay ( framingRange . start ) ;
var endMarker = framingRange . end ;
var instanceStarts = [ ] ;
while ( dayMarker < endMarker ) {
var instanceStart
// if everyday, or this particular day-of-week
= void 0 ;
// if everyday, or this particular day-of-week
if ( ! dowHash || dowHash [ dayMarker . getUTCDay ( ) ] ) {
if ( startTime ) {
instanceStart = dateEnv . add ( dayMarker , startTime ) ;
}
else {
instanceStart = dayMarker ;
}
instanceStarts . push ( instanceStart ) ;
}
dayMarker = addDays ( dayMarker , 1 ) ;
}
return instanceStarts ;
}
var DefaultOptionChangeHandlers = createPlugin ( {
optionChangeHandlers : {
events : function ( events , calendar , deepEqual ) {
handleEventSources ( [ events ] , calendar , deepEqual ) ;
} ,
eventSources : handleEventSources ,
plugins : handlePlugins
}
} ) ;
function handleEventSources ( inputs , calendar , deepEqual ) {
var unfoundSources = hashValuesToArray ( calendar . state . eventSources ) ;
var newInputs = [ ] ;
for ( var _i = 0 , inputs _1 = inputs ; _i < inputs _1 . length ; _i ++ ) {
var input = inputs _1 [ _i ] ;
var inputFound = false ;
for ( var i = 0 ; i < unfoundSources . length ; i ++ ) {
if ( deepEqual ( unfoundSources [ i ] . _raw , input ) ) {
unfoundSources . splice ( i , 1 ) ; // delete
inputFound = true ;
break ;
}
}
if ( ! inputFound ) {
newInputs . push ( input ) ;
}
}
for ( var _a = 0 , unfoundSources _1 = unfoundSources ; _a < unfoundSources _1 . length ; _a ++ ) {
var unfoundSource = unfoundSources _1 [ _a ] ;
calendar . dispatch ( {
type : 'REMOVE_EVENT_SOURCE' ,
sourceId : unfoundSource . sourceId
} ) ;
}
for ( var _b = 0 , newInputs _1 = newInputs ; _b < newInputs _1 . length ; _b ++ ) {
var newInput = newInputs _1 [ _b ] ;
calendar . addEventSource ( newInput ) ;
}
}
// shortcoming: won't remove plugins
function handlePlugins ( inputs , calendar ) {
calendar . addPluginInputs ( inputs ) ; // will gracefully handle duplicates
}
var config = { } ; // TODO: make these options
var globalDefaults = {
defaultRangeSeparator : ' - ' ,
titleRangeSeparator : ' \u2013 ' ,
defaultTimedEventDuration : '01:00:00' ,
defaultAllDayEventDuration : { day : 1 } ,
forceEventDuration : false ,
nextDayThreshold : '00:00:00' ,
// display
columnHeader : true ,
defaultView : '' ,
aspectRatio : 1.35 ,
header : {
left : 'title' ,
center : '' ,
right : 'today prev,next'
} ,
weekends : true ,
weekNumbers : false ,
weekNumberCalculation : 'local' ,
editable : false ,
// nowIndicator: false,
scrollTime : '06:00:00' ,
minTime : '00:00:00' ,
maxTime : '24:00:00' ,
showNonCurrentDates : true ,
// event ajax
lazyFetching : true ,
startParam : 'start' ,
endParam : 'end' ,
timeZoneParam : 'timeZone' ,
timeZone : 'local' ,
// allDayDefault: undefined,
// locale
locales : [ ] ,
locale : '' ,
// dir: will get this from the default locale
// buttonIcons: null,
// allows setting a min-height to the event segment to prevent short events overlapping each other
timeGridEventMinHeight : 0 ,
themeSystem : 'standard' ,
// eventResizableFromStart: false,
dragRevertDuration : 500 ,
dragScroll : true ,
allDayMaintainDuration : false ,
// selectable: false,
unselectAuto : true ,
// selectMinDistance: 0,
dropAccept : '*' ,
eventOrder : 'start,-duration,allDay,title' ,
// ^ if start tie, longer events go before shorter. final tie-breaker is title text
// rerenderDelay: null,
eventLimit : false ,
eventLimitClick : 'popover' ,
dayPopoverFormat : { month : 'long' , day : 'numeric' , year : 'numeric' } ,
handleWindowResize : true ,
windowResizeDelay : 100 ,
longPressDelay : 1000 ,
eventDragMinDistance : 5 // only applies to mouse
} ;
var rtlDefaults = {
header : {
left : 'next,prev today' ,
center : '' ,
right : 'title'
} ,
buttonIcons : {
// TODO: make RTL support the responibility of the theme
prev : 'fc-icon-chevron-right' ,
next : 'fc-icon-chevron-left' ,
prevYear : 'fc-icon-chevrons-right' ,
nextYear : 'fc-icon-chevrons-left'
}
} ;
var complexOptions = [
'header' ,
'footer' ,
'buttonText' ,
'buttonIcons'
] ;
// Merges an array of option objects into a single object
function mergeOptions ( optionObjs ) {
return mergeProps ( optionObjs , complexOptions ) ;
}
// TODO: move this stuff to a "plugin"-related file...
var INTERNAL _PLUGINS = [
ArrayEventSourcePlugin ,
FuncEventSourcePlugin ,
JsonFeedEventSourcePlugin ,
SimpleRecurrencePlugin ,
DefaultOptionChangeHandlers
] ;
function refinePluginDefs ( pluginInputs ) {
var plugins = [ ] ;
for ( var _i = 0 , pluginInputs _1 = pluginInputs ; _i < pluginInputs _1 . length ; _i ++ ) {
var pluginInput = pluginInputs _1 [ _i ] ;
if ( typeof pluginInput === 'string' ) {
var globalName = 'FullCalendar' + capitaliseFirstLetter ( pluginInput ) ;
if ( ! window [ globalName ] ) {
console . warn ( 'Plugin file not loaded for ' + pluginInput ) ;
}
else {
plugins . push ( window [ globalName ] . default ) ; // is an ES6 module
}
}
else {
plugins . push ( pluginInput ) ;
}
}
return INTERNAL _PLUGINS . concat ( plugins ) ;
}
var RAW _EN _LOCALE = {
code : 'en' ,
week : {
dow : 0 ,
doy : 4 // 4 days need to be within the year to be considered the first week
} ,
dir : 'ltr' ,
buttonText : {
prev : 'prev' ,
next : 'next' ,
prevYear : 'prev year' ,
nextYear : 'next year' ,
year : 'year' ,
today : 'today' ,
month : 'month' ,
week : 'week' ,
day : 'day' ,
list : 'list'
} ,
weekLabel : 'W' ,
allDayText : 'all-day' ,
eventLimitText : 'more' ,
noEventsMessage : 'No events to display'
} ;
function parseRawLocales ( explicitRawLocales ) {
var defaultCode = explicitRawLocales . length > 0 ? explicitRawLocales [ 0 ] . code : 'en' ;
var globalArray = window [ 'FullCalendarLocalesAll' ] || [ ] ; // from locales-all.js
var globalObject = window [ 'FullCalendarLocales' ] || { } ; // from locales/*.js. keys are meaningless
var allRawLocales = globalArray . concat ( // globalArray is low prio
hashValuesToArray ( globalObject ) , // medium prio
explicitRawLocales // highest prio
) ;
var rawLocaleMap = {
en : RAW _EN _LOCALE // necessary?
} ;
for ( var _i = 0 , allRawLocales _1 = allRawLocales ; _i < allRawLocales _1 . length ; _i ++ ) {
var rawLocale = allRawLocales _1 [ _i ] ;
rawLocaleMap [ rawLocale . code ] = rawLocale ;
}
return {
map : rawLocaleMap ,
defaultCode : defaultCode
} ;
}
function buildLocale ( inputSingular , available ) {
if ( typeof inputSingular === 'object' && ! Array . isArray ( inputSingular ) ) {
return parseLocale ( inputSingular . code , [ inputSingular . code ] , inputSingular ) ;
}
else {
return queryLocale ( inputSingular , available ) ;
}
}
function queryLocale ( codeArg , available ) {
var codes = [ ] . concat ( codeArg || [ ] ) ; // will convert to array
var raw = queryRawLocale ( codes , available ) || RAW _EN _LOCALE ;
return parseLocale ( codeArg , codes , raw ) ;
}
function queryRawLocale ( codes , available ) {
for ( var i = 0 ; i < codes . length ; i ++ ) {
var parts = codes [ i ] . toLocaleLowerCase ( ) . split ( '-' ) ;
for ( var j = parts . length ; j > 0 ; j -- ) {
var simpleId = parts . slice ( 0 , j ) . join ( '-' ) ;
if ( available [ simpleId ] ) {
return available [ simpleId ] ;
}
}
}
return null ;
}
function parseLocale ( codeArg , codes , raw ) {
var merged = mergeProps ( [ RAW _EN _LOCALE , raw ] , [ 'buttonText' ] ) ;
delete merged . code ; // don't want this part of the options
var week = merged . week ;
delete merged . week ;
return {
codeArg : codeArg ,
codes : codes ,
week : week ,
simpleNumberFormat : new Intl . NumberFormat ( codeArg ) ,
options : merged
} ;
}
var OptionsManager = /** @class */ ( function ( ) {
function OptionsManager ( overrides ) {
this . overrides = _ _assign ( { } , overrides ) ; // make a copy
this . dynamicOverrides = { } ;
this . compute ( ) ;
}
OptionsManager . prototype . mutate = function ( updates , removals , isDynamic ) {
2020-04-01 22:52:43 +00:00
if ( ! Object . keys ( updates ) . length && ! removals . length ) {
return ;
}
2019-08-28 10:59:33 +00:00
var overrideHash = isDynamic ? this . dynamicOverrides : this . overrides ;
_ _assign ( overrideHash , updates ) ;
for ( var _i = 0 , removals _1 = removals ; _i < removals _1 . length ; _i ++ ) {
var propName = removals _1 [ _i ] ;
delete overrideHash [ propName ] ;
}
this . compute ( ) ;
} ;
// Computes the flattened options hash for the calendar and assigns to `this.options`.
// Assumes this.overrides and this.dynamicOverrides have already been initialized.
OptionsManager . prototype . compute = function ( ) {
// TODO: not a very efficient system
var locales = firstDefined ( // explicit locale option given?
this . dynamicOverrides . locales , this . overrides . locales , globalDefaults . locales ) ;
var locale = firstDefined ( // explicit locales option given?
this . dynamicOverrides . locale , this . overrides . locale , globalDefaults . locale ) ;
var available = parseRawLocales ( locales ) ;
var localeDefaults = buildLocale ( locale || available . defaultCode , available . map ) . options ;
var dir = firstDefined ( // based on options computed so far, is direction RTL?
this . dynamicOverrides . dir , this . overrides . dir , localeDefaults . dir ) ;
var dirDefaults = dir === 'rtl' ? rtlDefaults : { } ;
this . dirDefaults = dirDefaults ;
this . localeDefaults = localeDefaults ;
this . computed = mergeOptions ( [
globalDefaults ,
dirDefaults ,
localeDefaults ,
this . overrides ,
this . dynamicOverrides
] ) ;
} ;
return OptionsManager ;
} ( ) ) ;
var calendarSystemClassMap = { } ;
function registerCalendarSystem ( name , theClass ) {
calendarSystemClassMap [ name ] = theClass ;
}
function createCalendarSystem ( name ) {
return new calendarSystemClassMap [ name ] ( ) ;
}
var GregorianCalendarSystem = /** @class */ ( function ( ) {
function GregorianCalendarSystem ( ) {
}
GregorianCalendarSystem . prototype . getMarkerYear = function ( d ) {
return d . getUTCFullYear ( ) ;
} ;
GregorianCalendarSystem . prototype . getMarkerMonth = function ( d ) {
return d . getUTCMonth ( ) ;
} ;
GregorianCalendarSystem . prototype . getMarkerDay = function ( d ) {
return d . getUTCDate ( ) ;
} ;
GregorianCalendarSystem . prototype . arrayToMarker = function ( arr ) {
return arrayToUtcDate ( arr ) ;
} ;
GregorianCalendarSystem . prototype . markerToArray = function ( marker ) {
return dateToUtcArray ( marker ) ;
} ;
return GregorianCalendarSystem ;
} ( ) ) ;
registerCalendarSystem ( 'gregory' , GregorianCalendarSystem ) ;
var ISO _RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/ ;
function parse ( str ) {
var m = ISO _RE . exec ( str ) ;
if ( m ) {
var marker = new Date ( Date . UTC ( Number ( m [ 1 ] ) , m [ 3 ] ? Number ( m [ 3 ] ) - 1 : 0 , Number ( m [ 5 ] || 1 ) , Number ( m [ 7 ] || 0 ) , Number ( m [ 8 ] || 0 ) , Number ( m [ 10 ] || 0 ) , m [ 12 ] ? Number ( '0.' + m [ 12 ] ) * 1000 : 0 ) ) ;
if ( isValidDate ( marker ) ) {
var timeZoneOffset = null ;
if ( m [ 13 ] ) {
timeZoneOffset = ( m [ 15 ] === '-' ? - 1 : 1 ) * ( Number ( m [ 16 ] || 0 ) * 60 +
Number ( m [ 18 ] || 0 ) ) ;
}
return {
marker : marker ,
isTimeUnspecified : ! m [ 6 ] ,
timeZoneOffset : timeZoneOffset
} ;
}
}
return null ;
}
var DateEnv = /** @class */ ( function ( ) {
function DateEnv ( settings ) {
var timeZone = this . timeZone = settings . timeZone ;
var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC' ;
if ( settings . namedTimeZoneImpl && isNamedTimeZone ) {
this . namedTimeZoneImpl = new settings . namedTimeZoneImpl ( timeZone ) ;
}
this . canComputeOffset = Boolean ( ! isNamedTimeZone || this . namedTimeZoneImpl ) ;
this . calendarSystem = createCalendarSystem ( settings . calendarSystem ) ;
this . locale = settings . locale ;
this . weekDow = settings . locale . week . dow ;
this . weekDoy = settings . locale . week . doy ;
if ( settings . weekNumberCalculation === 'ISO' ) {
this . weekDow = 1 ;
this . weekDoy = 4 ;
}
if ( typeof settings . firstDay === 'number' ) {
this . weekDow = settings . firstDay ;
}
if ( typeof settings . weekNumberCalculation === 'function' ) {
this . weekNumberFunc = settings . weekNumberCalculation ;
}
this . weekLabel = settings . weekLabel != null ? settings . weekLabel : settings . locale . options . weekLabel ;
this . cmdFormatter = settings . cmdFormatter ;
}
// Creating / Parsing
DateEnv . prototype . createMarker = function ( input ) {
var meta = this . createMarkerMeta ( input ) ;
if ( meta === null ) {
return null ;
}
return meta . marker ;
} ;
DateEnv . prototype . createNowMarker = function ( ) {
if ( this . canComputeOffset ) {
return this . timestampToMarker ( new Date ( ) . valueOf ( ) ) ;
}
else {
// if we can't compute the current date val for a timezone,
// better to give the current local date vals than UTC
return arrayToUtcDate ( dateToLocalArray ( new Date ( ) ) ) ;
}
} ;
DateEnv . prototype . createMarkerMeta = function ( input ) {
if ( typeof input === 'string' ) {
return this . parse ( input ) ;
}
var marker = null ;
if ( typeof input === 'number' ) {
marker = this . timestampToMarker ( input ) ;
}
else if ( input instanceof Date ) {
input = input . valueOf ( ) ;
if ( ! isNaN ( input ) ) {
marker = this . timestampToMarker ( input ) ;
}
}
else if ( Array . isArray ( input ) ) {
marker = arrayToUtcDate ( input ) ;
}
if ( marker === null || ! isValidDate ( marker ) ) {
return null ;
}
return { marker : marker , isTimeUnspecified : false , forcedTzo : null } ;
} ;
DateEnv . prototype . parse = function ( s ) {
var parts = parse ( s ) ;
if ( parts === null ) {
return null ;
}
var marker = parts . marker ;
var forcedTzo = null ;
if ( parts . timeZoneOffset !== null ) {
if ( this . canComputeOffset ) {
marker = this . timestampToMarker ( marker . valueOf ( ) - parts . timeZoneOffset * 60 * 1000 ) ;
}
else {
forcedTzo = parts . timeZoneOffset ;
}
}
return { marker : marker , isTimeUnspecified : parts . isTimeUnspecified , forcedTzo : forcedTzo } ;
} ;
// Accessors
DateEnv . prototype . getYear = function ( marker ) {
return this . calendarSystem . getMarkerYear ( marker ) ;
} ;
DateEnv . prototype . getMonth = function ( marker ) {
return this . calendarSystem . getMarkerMonth ( marker ) ;
} ;
// Adding / Subtracting
DateEnv . prototype . add = function ( marker , dur ) {
var a = this . calendarSystem . markerToArray ( marker ) ;
a [ 0 ] += dur . years ;
a [ 1 ] += dur . months ;
a [ 2 ] += dur . days ;
a [ 6 ] += dur . milliseconds ;
return this . calendarSystem . arrayToMarker ( a ) ;
} ;
DateEnv . prototype . subtract = function ( marker , dur ) {
var a = this . calendarSystem . markerToArray ( marker ) ;
a [ 0 ] -= dur . years ;
a [ 1 ] -= dur . months ;
a [ 2 ] -= dur . days ;
a [ 6 ] -= dur . milliseconds ;
return this . calendarSystem . arrayToMarker ( a ) ;
} ;
DateEnv . prototype . addYears = function ( marker , n ) {
var a = this . calendarSystem . markerToArray ( marker ) ;
a [ 0 ] += n ;
return this . calendarSystem . arrayToMarker ( a ) ;
} ;
DateEnv . prototype . addMonths = function ( marker , n ) {
var a = this . calendarSystem . markerToArray ( marker ) ;
a [ 1 ] += n ;
return this . calendarSystem . arrayToMarker ( a ) ;
} ;
// Diffing Whole Units
DateEnv . prototype . diffWholeYears = function ( m0 , m1 ) {
var calendarSystem = this . calendarSystem ;
if ( timeAsMs ( m0 ) === timeAsMs ( m1 ) &&
calendarSystem . getMarkerDay ( m0 ) === calendarSystem . getMarkerDay ( m1 ) &&
calendarSystem . getMarkerMonth ( m0 ) === calendarSystem . getMarkerMonth ( m1 ) ) {
return calendarSystem . getMarkerYear ( m1 ) - calendarSystem . getMarkerYear ( m0 ) ;
}
return null ;
} ;
DateEnv . prototype . diffWholeMonths = function ( m0 , m1 ) {
var calendarSystem = this . calendarSystem ;
if ( timeAsMs ( m0 ) === timeAsMs ( m1 ) &&
calendarSystem . getMarkerDay ( m0 ) === calendarSystem . getMarkerDay ( m1 ) ) {
return ( calendarSystem . getMarkerMonth ( m1 ) - calendarSystem . getMarkerMonth ( m0 ) ) +
( calendarSystem . getMarkerYear ( m1 ) - calendarSystem . getMarkerYear ( m0 ) ) * 12 ;
}
return null ;
} ;
// Range / Duration
DateEnv . prototype . greatestWholeUnit = function ( m0 , m1 ) {
var n = this . diffWholeYears ( m0 , m1 ) ;
if ( n !== null ) {
return { unit : 'year' , value : n } ;
}
n = this . diffWholeMonths ( m0 , m1 ) ;
if ( n !== null ) {
return { unit : 'month' , value : n } ;
}
n = diffWholeWeeks ( m0 , m1 ) ;
if ( n !== null ) {
return { unit : 'week' , value : n } ;
}
n = diffWholeDays ( m0 , m1 ) ;
if ( n !== null ) {
return { unit : 'day' , value : n } ;
}
n = diffHours ( m0 , m1 ) ;
if ( isInt ( n ) ) {
return { unit : 'hour' , value : n } ;
}
n = diffMinutes ( m0 , m1 ) ;
if ( isInt ( n ) ) {
return { unit : 'minute' , value : n } ;
}
n = diffSeconds ( m0 , m1 ) ;
if ( isInt ( n ) ) {
return { unit : 'second' , value : n } ;
}
return { unit : 'millisecond' , value : m1 . valueOf ( ) - m0 . valueOf ( ) } ;
} ;
DateEnv . prototype . countDurationsBetween = function ( m0 , m1 , d ) {
// TODO: can use greatestWholeUnit
var diff ;
if ( d . years ) {
diff = this . diffWholeYears ( m0 , m1 ) ;
if ( diff !== null ) {
return diff / asRoughYears ( d ) ;
}
}
if ( d . months ) {
diff = this . diffWholeMonths ( m0 , m1 ) ;
if ( diff !== null ) {
return diff / asRoughMonths ( d ) ;
}
}
if ( d . days ) {
diff = diffWholeDays ( m0 , m1 ) ;
if ( diff !== null ) {
return diff / asRoughDays ( d ) ;
}
}
return ( m1 . valueOf ( ) - m0 . valueOf ( ) ) / asRoughMs ( d ) ;
} ;
// Start-Of
DateEnv . prototype . startOf = function ( m , unit ) {
if ( unit === 'year' ) {
return this . startOfYear ( m ) ;
}
else if ( unit === 'month' ) {
return this . startOfMonth ( m ) ;
}
else if ( unit === 'week' ) {
return this . startOfWeek ( m ) ;
}
else if ( unit === 'day' ) {
return startOfDay ( m ) ;
}
else if ( unit === 'hour' ) {
return startOfHour ( m ) ;
}
else if ( unit === 'minute' ) {
return startOfMinute ( m ) ;
}
else if ( unit === 'second' ) {
return startOfSecond ( m ) ;
}
} ;
DateEnv . prototype . startOfYear = function ( m ) {
return this . calendarSystem . arrayToMarker ( [
this . calendarSystem . getMarkerYear ( m )
] ) ;
} ;
DateEnv . prototype . startOfMonth = function ( m ) {
return this . calendarSystem . arrayToMarker ( [
this . calendarSystem . getMarkerYear ( m ) ,
this . calendarSystem . getMarkerMonth ( m )
] ) ;
} ;
DateEnv . prototype . startOfWeek = function ( m ) {
return this . calendarSystem . arrayToMarker ( [
this . calendarSystem . getMarkerYear ( m ) ,
this . calendarSystem . getMarkerMonth ( m ) ,
m . getUTCDate ( ) - ( ( m . getUTCDay ( ) - this . weekDow + 7 ) % 7 )
] ) ;
} ;
// Week Number
DateEnv . prototype . computeWeekNumber = function ( marker ) {
if ( this . weekNumberFunc ) {
return this . weekNumberFunc ( this . toDate ( marker ) ) ;
}
else {
return weekOfYear ( marker , this . weekDow , this . weekDoy ) ;
}
} ;
// TODO: choke on timeZoneName: long
DateEnv . prototype . format = function ( marker , formatter , dateOptions ) {
if ( dateOptions === void 0 ) { dateOptions = { } ; }
return formatter . format ( {
marker : marker ,
timeZoneOffset : dateOptions . forcedTzo != null ?
dateOptions . forcedTzo :
this . offsetForMarker ( marker )
} , this ) ;
} ;
DateEnv . prototype . formatRange = function ( start , end , formatter , dateOptions ) {
if ( dateOptions === void 0 ) { dateOptions = { } ; }
if ( dateOptions . isEndExclusive ) {
end = addMs ( end , - 1 ) ;
}
return formatter . formatRange ( {
marker : start ,
timeZoneOffset : dateOptions . forcedStartTzo != null ?
dateOptions . forcedStartTzo :
this . offsetForMarker ( start )
} , {
marker : end ,
timeZoneOffset : dateOptions . forcedEndTzo != null ?
dateOptions . forcedEndTzo :
this . offsetForMarker ( end )
} , this ) ;
} ;
DateEnv . prototype . formatIso = function ( marker , extraOptions ) {
if ( extraOptions === void 0 ) { extraOptions = { } ; }
var timeZoneOffset = null ;
if ( ! extraOptions . omitTimeZoneOffset ) {
if ( extraOptions . forcedTzo != null ) {
timeZoneOffset = extraOptions . forcedTzo ;
}
else {
timeZoneOffset = this . offsetForMarker ( marker ) ;
}
}
return buildIsoString ( marker , timeZoneOffset , extraOptions . omitTime ) ;
} ;
// TimeZone
DateEnv . prototype . timestampToMarker = function ( ms ) {
if ( this . timeZone === 'local' ) {
return arrayToUtcDate ( dateToLocalArray ( new Date ( ms ) ) ) ;
}
else if ( this . timeZone === 'UTC' || ! this . namedTimeZoneImpl ) {
return new Date ( ms ) ;
}
else {
return arrayToUtcDate ( this . namedTimeZoneImpl . timestampToArray ( ms ) ) ;
}
} ;
DateEnv . prototype . offsetForMarker = function ( m ) {
if ( this . timeZone === 'local' ) {
return - arrayToLocalDate ( dateToUtcArray ( m ) ) . getTimezoneOffset ( ) ; // convert "inverse" offset to "normal" offset
}
else if ( this . timeZone === 'UTC' ) {
return 0 ;
}
else if ( this . namedTimeZoneImpl ) {
return this . namedTimeZoneImpl . offsetForArray ( dateToUtcArray ( m ) ) ;
}
return null ;
} ;
// Conversion
DateEnv . prototype . toDate = function ( m , forcedTzo ) {
if ( this . timeZone === 'local' ) {
return arrayToLocalDate ( dateToUtcArray ( m ) ) ;
}
else if ( this . timeZone === 'UTC' ) {
return new Date ( m . valueOf ( ) ) ; // make sure it's a copy
}
else if ( ! this . namedTimeZoneImpl ) {
return new Date ( m . valueOf ( ) - ( forcedTzo || 0 ) ) ;
}
else {
return new Date ( m . valueOf ( ) -
this . namedTimeZoneImpl . offsetForArray ( dateToUtcArray ( m ) ) * 1000 * 60 // convert minutes -> ms
) ;
}
} ;
return DateEnv ;
} ( ) ) ;
var SIMPLE _SOURCE _PROPS = {
id : String ,
allDayDefault : Boolean ,
eventDataTransform : Function ,
success : Function ,
failure : Function
} ;
var uid$2 = 0 ;
function doesSourceNeedRange ( eventSource , calendar ) {
var defs = calendar . pluginSystem . hooks . eventSourceDefs ;
return ! defs [ eventSource . sourceDefId ] . ignoreRange ;
}
function parseEventSource ( raw , calendar ) {
var defs = calendar . pluginSystem . hooks . eventSourceDefs ;
for ( var i = defs . length - 1 ; i >= 0 ; i -- ) { // later-added plugins take precedence
var def = defs [ i ] ;
var meta = def . parseMeta ( raw ) ;
if ( meta ) {
var res = parseEventSourceProps ( typeof raw === 'object' ? raw : { } , meta , i , calendar ) ;
res . _raw = raw ;
return res ;
}
}
return null ;
}
function parseEventSourceProps ( raw , meta , sourceDefId , calendar ) {
var leftovers0 = { } ;
var props = refineProps ( raw , SIMPLE _SOURCE _PROPS , { } , leftovers0 ) ;
var leftovers1 = { } ;
var ui = processUnscopedUiProps ( leftovers0 , calendar , leftovers1 ) ;
props . isFetching = false ;
props . latestFetchId = '' ;
props . fetchRange = null ;
props . publicId = String ( raw . id || '' ) ;
props . sourceId = String ( uid$2 ++ ) ;
props . sourceDefId = sourceDefId ;
props . meta = meta ;
props . ui = ui ;
props . extendedProps = leftovers1 ;
return props ;
}
function reduceEventSources ( eventSources , action , dateProfile , calendar ) {
switch ( action . type ) {
case 'ADD_EVENT_SOURCES' : // already parsed
return addSources ( eventSources , action . sources , dateProfile ? dateProfile . activeRange : null , calendar ) ;
case 'REMOVE_EVENT_SOURCE' :
return removeSource ( eventSources , action . sourceId ) ;
case 'PREV' : // TODO: how do we track all actions that affect dateProfile :(
case 'NEXT' :
case 'SET_DATE' :
case 'SET_VIEW_TYPE' :
if ( dateProfile ) {
return fetchDirtySources ( eventSources , dateProfile . activeRange , calendar ) ;
}
else {
return eventSources ;
}
case 'FETCH_EVENT_SOURCES' :
case 'CHANGE_TIMEZONE' :
return fetchSourcesByIds ( eventSources , action . sourceIds ?
arrayToHash ( action . sourceIds ) :
excludeStaticSources ( eventSources , calendar ) , dateProfile ? dateProfile . activeRange : null , calendar ) ;
case 'RECEIVE_EVENTS' :
case 'RECEIVE_EVENT_ERROR' :
return receiveResponse ( eventSources , action . sourceId , action . fetchId , action . fetchRange ) ;
case 'REMOVE_ALL_EVENT_SOURCES' :
return { } ;
default :
return eventSources ;
}
}
var uid$3 = 0 ;
function addSources ( eventSourceHash , sources , fetchRange , calendar ) {
var hash = { } ;
for ( var _i = 0 , sources _1 = sources ; _i < sources _1 . length ; _i ++ ) {
var source = sources _1 [ _i ] ;
hash [ source . sourceId ] = source ;
}
if ( fetchRange ) {
hash = fetchDirtySources ( hash , fetchRange , calendar ) ;
}
return _ _assign ( { } , eventSourceHash , hash ) ;
}
function removeSource ( eventSourceHash , sourceId ) {
return filterHash ( eventSourceHash , function ( eventSource ) {
return eventSource . sourceId !== sourceId ;
} ) ;
}
function fetchDirtySources ( sourceHash , fetchRange , calendar ) {
return fetchSourcesByIds ( sourceHash , filterHash ( sourceHash , function ( eventSource ) {
return isSourceDirty ( eventSource , fetchRange , calendar ) ;
} ) , fetchRange , calendar ) ;
}
function isSourceDirty ( eventSource , fetchRange , calendar ) {
if ( ! doesSourceNeedRange ( eventSource , calendar ) ) {
return ! eventSource . latestFetchId ;
}
else {
return ! calendar . opt ( 'lazyFetching' ) ||
! eventSource . fetchRange ||
2020-04-01 22:52:43 +00:00
eventSource . isFetching || // always cancel outdated in-progress fetches
2019-08-28 10:59:33 +00:00
fetchRange . start < eventSource . fetchRange . start ||
fetchRange . end > eventSource . fetchRange . end ;
}
}
function fetchSourcesByIds ( prevSources , sourceIdHash , fetchRange , calendar ) {
var nextSources = { } ;
for ( var sourceId in prevSources ) {
var source = prevSources [ sourceId ] ;
if ( sourceIdHash [ sourceId ] ) {
nextSources [ sourceId ] = fetchSource ( source , fetchRange , calendar ) ;
}
else {
nextSources [ sourceId ] = source ;
}
}
return nextSources ;
}
function fetchSource ( eventSource , fetchRange , calendar ) {
var sourceDef = calendar . pluginSystem . hooks . eventSourceDefs [ eventSource . sourceDefId ] ;
var fetchId = String ( uid$3 ++ ) ;
sourceDef . fetch ( {
eventSource : eventSource ,
calendar : calendar ,
range : fetchRange
} , function ( res ) {
var rawEvents = res . rawEvents ;
var calSuccess = calendar . opt ( 'eventSourceSuccess' ) ;
var calSuccessRes ;
var sourceSuccessRes ;
if ( eventSource . success ) {
sourceSuccessRes = eventSource . success ( rawEvents , res . xhr ) ;
}
if ( calSuccess ) {
calSuccessRes = calSuccess ( rawEvents , res . xhr ) ;
}
rawEvents = sourceSuccessRes || calSuccessRes || rawEvents ;
calendar . dispatch ( {
type : 'RECEIVE_EVENTS' ,
sourceId : eventSource . sourceId ,
fetchId : fetchId ,
fetchRange : fetchRange ,
rawEvents : rawEvents
} ) ;
} , function ( error ) {
var callFailure = calendar . opt ( 'eventSourceFailure' ) ;
console . warn ( error . message , error ) ;
if ( eventSource . failure ) {
eventSource . failure ( error ) ;
}
if ( callFailure ) {
callFailure ( error ) ;
}
calendar . dispatch ( {
type : 'RECEIVE_EVENT_ERROR' ,
sourceId : eventSource . sourceId ,
fetchId : fetchId ,
fetchRange : fetchRange ,
error : error
} ) ;
} ) ;
return _ _assign ( { } , eventSource , { isFetching : true , latestFetchId : fetchId } ) ;
}
function receiveResponse ( sourceHash , sourceId , fetchId , fetchRange ) {
var _a ;
var eventSource = sourceHash [ sourceId ] ;
if ( eventSource && // not already removed
fetchId === eventSource . latestFetchId ) {
2020-04-01 22:52:43 +00:00
return _ _assign ( { } , sourceHash , ( _a = { } , _a [ sourceId ] = _ _assign ( { } , eventSource , { isFetching : false , fetchRange : fetchRange // also serves as a marker that at least one fetch has completed
} ) , _a ) ) ;
2019-08-28 10:59:33 +00:00
}
return sourceHash ;
}
function excludeStaticSources ( eventSources , calendar ) {
return filterHash ( eventSources , function ( eventSource ) {
return doesSourceNeedRange ( eventSource , calendar ) ;
} ) ;
}
var DateProfileGenerator = /** @class */ ( function ( ) {
function DateProfileGenerator ( viewSpec , calendar ) {
this . viewSpec = viewSpec ;
this . options = viewSpec . options ;
this . dateEnv = calendar . dateEnv ;
this . calendar = calendar ;
this . initHiddenDays ( ) ;
}
/ * D a t e R a n g e C o m p u t a t i o n
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
// Builds a structure with info about what the dates/ranges will be for the "prev" view.
DateProfileGenerator . prototype . buildPrev = function ( currentDateProfile , currentDate ) {
var dateEnv = this . dateEnv ;
var prevDate = dateEnv . subtract ( dateEnv . startOf ( currentDate , currentDateProfile . currentRangeUnit ) , // important for start-of-month
currentDateProfile . dateIncrement ) ;
return this . build ( prevDate , - 1 ) ;
} ;
// Builds a structure with info about what the dates/ranges will be for the "next" view.
DateProfileGenerator . prototype . buildNext = function ( currentDateProfile , currentDate ) {
var dateEnv = this . dateEnv ;
var nextDate = dateEnv . add ( dateEnv . startOf ( currentDate , currentDateProfile . currentRangeUnit ) , // important for start-of-month
currentDateProfile . dateIncrement ) ;
return this . build ( nextDate , 1 ) ;
} ;
// Builds a structure holding dates/ranges for rendering around the given date.
// Optional direction param indicates whether the date is being incremented/decremented
// from its previous value. decremented = -1, incremented = 1 (default).
DateProfileGenerator . prototype . build = function ( currentDate , direction , forceToValid ) {
if ( forceToValid === void 0 ) { forceToValid = false ; }
var validRange ;
var minTime = null ;
var maxTime = null ;
var currentInfo ;
var isRangeAllDay ;
var renderRange ;
var activeRange ;
var isValid ;
validRange = this . buildValidRange ( ) ;
validRange = this . trimHiddenDays ( validRange ) ;
if ( forceToValid ) {
currentDate = constrainMarkerToRange ( currentDate , validRange ) ;
}
currentInfo = this . buildCurrentRangeInfo ( currentDate , direction ) ;
isRangeAllDay = /^(year|month|week|day)$/ . test ( currentInfo . unit ) ;
renderRange = this . buildRenderRange ( this . trimHiddenDays ( currentInfo . range ) , currentInfo . unit , isRangeAllDay ) ;
renderRange = this . trimHiddenDays ( renderRange ) ;
activeRange = renderRange ;
if ( ! this . options . showNonCurrentDates ) {
activeRange = intersectRanges ( activeRange , currentInfo . range ) ;
}
minTime = createDuration ( this . options . minTime ) ;
maxTime = createDuration ( this . options . maxTime ) ;
activeRange = this . adjustActiveRange ( activeRange , minTime , maxTime ) ;
activeRange = intersectRanges ( activeRange , validRange ) ; // might return null
// it's invalid if the originally requested date is not contained,
// or if the range is completely outside of the valid range.
isValid = rangesIntersect ( currentInfo . range , validRange ) ;
return {
// constraint for where prev/next operations can go and where events can be dragged/resized to.
// an object with optional start and end properties.
validRange : validRange ,
// range the view is formally responsible for.
// for example, a month view might have 1st-31st, excluding padded dates
currentRange : currentInfo . range ,
// name of largest unit being displayed, like "month" or "week"
currentRangeUnit : currentInfo . unit ,
isRangeAllDay : isRangeAllDay ,
// dates that display events and accept drag-n-drop
// will be `null` if no dates accept events
activeRange : activeRange ,
// date range with a rendered skeleton
// includes not-active days that need some sort of DOM
renderRange : renderRange ,
// Duration object that denotes the first visible time of any given day
minTime : minTime ,
// Duration object that denotes the exclusive visible end time of any given day
maxTime : maxTime ,
isValid : isValid ,
// how far the current date will move for a prev/next operation
dateIncrement : this . buildDateIncrement ( currentInfo . duration )
// pass a fallback (might be null) ^
} ;
} ;
// Builds an object with optional start/end properties.
// Indicates the minimum/maximum dates to display.
// not responsible for trimming hidden days.
DateProfileGenerator . prototype . buildValidRange = function ( ) {
return this . getRangeOption ( 'validRange' , this . calendar . getNow ( ) ) ||
{ start : null , end : null } ; // completely open-ended
} ;
// Builds a structure with info about the "current" range, the range that is
// highlighted as being the current month for example.
// See build() for a description of `direction`.
// Guaranteed to have `range` and `unit` properties. `duration` is optional.
DateProfileGenerator . prototype . buildCurrentRangeInfo = function ( date , direction ) {
var _a = this , viewSpec = _a . viewSpec , dateEnv = _a . dateEnv ;
var duration = null ;
var unit = null ;
var range = null ;
var dayCount ;
if ( viewSpec . duration ) {
duration = viewSpec . duration ;
unit = viewSpec . durationUnit ;
range = this . buildRangeFromDuration ( date , direction , duration , unit ) ;
}
else if ( ( dayCount = this . options . dayCount ) ) {
unit = 'day' ;
range = this . buildRangeFromDayCount ( date , direction , dayCount ) ;
}
else if ( ( range = this . buildCustomVisibleRange ( date ) ) ) {
unit = dateEnv . greatestWholeUnit ( range . start , range . end ) . unit ;
}
else {
duration = this . getFallbackDuration ( ) ;
unit = greatestDurationDenominator ( duration ) . unit ;
range = this . buildRangeFromDuration ( date , direction , duration , unit ) ;
}
return { duration : duration , unit : unit , range : range } ;
} ;
DateProfileGenerator . prototype . getFallbackDuration = function ( ) {
return createDuration ( { day : 1 } ) ;
} ;
// Returns a new activeRange to have time values (un-ambiguate)
// minTime or maxTime causes the range to expand.
DateProfileGenerator . prototype . adjustActiveRange = function ( range , minTime , maxTime ) {
var dateEnv = this . dateEnv ;
var start = range . start ;
var end = range . end ;
if ( this . viewSpec . class . prototype . usesMinMaxTime ) {
// expand active range if minTime is negative (why not when positive?)
if ( asRoughDays ( minTime ) < 0 ) {
start = startOfDay ( start ) ; // necessary?
start = dateEnv . add ( start , minTime ) ;
}
// expand active range if maxTime is beyond one day (why not when positive?)
if ( asRoughDays ( maxTime ) > 1 ) {
end = startOfDay ( end ) ; // necessary?
end = addDays ( end , - 1 ) ;
end = dateEnv . add ( end , maxTime ) ;
}
}
return { start : start , end : end } ;
} ;
// Builds the "current" range when it is specified as an explicit duration.
// `unit` is the already-computed greatestDurationDenominator unit of duration.
DateProfileGenerator . prototype . buildRangeFromDuration = function ( date , direction , duration , unit ) {
var dateEnv = this . dateEnv ;
var alignment = this . options . dateAlignment ;
var dateIncrementInput ;
var dateIncrementDuration ;
var start ;
var end ;
var res ;
// compute what the alignment should be
if ( ! alignment ) {
dateIncrementInput = this . options . dateIncrement ;
if ( dateIncrementInput ) {
dateIncrementDuration = createDuration ( dateIncrementInput ) ;
// use the smaller of the two units
if ( asRoughMs ( dateIncrementDuration ) < asRoughMs ( duration ) ) {
alignment = greatestDurationDenominator ( dateIncrementDuration , ! getWeeksFromInput ( dateIncrementInput ) ) . unit ;
}
else {
alignment = unit ;
}
}
else {
alignment = unit ;
}
}
// if the view displays a single day or smaller
if ( asRoughDays ( duration ) <= 1 ) {
if ( this . isHiddenDay ( start ) ) {
start = this . skipHiddenDays ( start , direction ) ;
start = startOfDay ( start ) ;
}
}
function computeRes ( ) {
start = dateEnv . startOf ( date , alignment ) ;
end = dateEnv . add ( start , duration ) ;
res = { start : start , end : end } ;
}
computeRes ( ) ;
// if range is completely enveloped by hidden days, go past the hidden days
if ( ! this . trimHiddenDays ( res ) ) {
date = this . skipHiddenDays ( date , direction ) ;
computeRes ( ) ;
}
return res ;
} ;
// Builds the "current" range when a dayCount is specified.
DateProfileGenerator . prototype . buildRangeFromDayCount = function ( date , direction , dayCount ) {
var dateEnv = this . dateEnv ;
var customAlignment = this . options . dateAlignment ;
var runningCount = 0 ;
var start = date ;
var end ;
if ( customAlignment ) {
start = dateEnv . startOf ( start , customAlignment ) ;
}
start = startOfDay ( start ) ;
start = this . skipHiddenDays ( start , direction ) ;
end = start ;
do {
end = addDays ( end , 1 ) ;
if ( ! this . isHiddenDay ( end ) ) {
runningCount ++ ;
}
} while ( runningCount < dayCount ) ;
return { start : start , end : end } ;
} ;
// Builds a normalized range object for the "visible" range,
// which is a way to define the currentRange and activeRange at the same time.
DateProfileGenerator . prototype . buildCustomVisibleRange = function ( date ) {
var dateEnv = this . dateEnv ;
var visibleRange = this . getRangeOption ( 'visibleRange' , dateEnv . toDate ( date ) ) ;
if ( visibleRange && ( visibleRange . start == null || visibleRange . end == null ) ) {
return null ;
}
return visibleRange ;
} ;
// Computes the range that will represent the element/cells for *rendering*,
// but which may have voided days/times.
// not responsible for trimming hidden days.
DateProfileGenerator . prototype . buildRenderRange = function ( currentRange , currentRangeUnit , isRangeAllDay ) {
return currentRange ;
} ;
// Compute the duration value that should be added/substracted to the current date
// when a prev/next operation happens.
DateProfileGenerator . prototype . buildDateIncrement = function ( fallback ) {
var dateIncrementInput = this . options . dateIncrement ;
var customAlignment ;
if ( dateIncrementInput ) {
return createDuration ( dateIncrementInput ) ;
}
else if ( ( customAlignment = this . options . dateAlignment ) ) {
return createDuration ( 1 , customAlignment ) ;
}
else if ( fallback ) {
return fallback ;
}
else {
return createDuration ( { days : 1 } ) ;
}
} ;
// Arguments after name will be forwarded to a hypothetical function value
// WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects.
// Always clone your objects if you fear mutation.
DateProfileGenerator . prototype . getRangeOption = function ( name ) {
var otherArgs = [ ] ;
for ( var _i = 1 ; _i < arguments . length ; _i ++ ) {
otherArgs [ _i - 1 ] = arguments [ _i ] ;
}
var val = this . options [ name ] ;
if ( typeof val === 'function' ) {
val = val . apply ( null , otherArgs ) ;
}
if ( val ) {
val = parseRange ( val , this . dateEnv ) ;
}
if ( val ) {
val = computeVisibleDayRange ( val ) ;
}
return val ;
} ;
/ * H i d d e n D a y s
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
// Initializes internal variables related to calculating hidden days-of-week
DateProfileGenerator . prototype . initHiddenDays = function ( ) {
var hiddenDays = this . options . hiddenDays || [ ] ; // array of day-of-week indices that are hidden
var isHiddenDayHash = [ ] ; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
var dayCnt = 0 ;
var i ;
if ( this . options . weekends === false ) {
hiddenDays . push ( 0 , 6 ) ; // 0=sunday, 6=saturday
}
for ( i = 0 ; i < 7 ; i ++ ) {
if ( ! ( isHiddenDayHash [ i ] = hiddenDays . indexOf ( i ) !== - 1 ) ) {
dayCnt ++ ;
}
}
if ( ! dayCnt ) {
throw new Error ( 'invalid hiddenDays' ) ; // all days were hidden? bad.
}
this . isHiddenDayHash = isHiddenDayHash ;
} ;
// Remove days from the beginning and end of the range that are computed as hidden.
// If the whole range is trimmed off, returns null
DateProfileGenerator . prototype . trimHiddenDays = function ( range ) {
var start = range . start ;
var end = range . end ;
if ( start ) {
start = this . skipHiddenDays ( start ) ;
}
if ( end ) {
end = this . skipHiddenDays ( end , - 1 , true ) ;
}
if ( start == null || end == null || start < end ) {
return { start : start , end : end } ;
}
return null ;
} ;
// Is the current day hidden?
// `day` is a day-of-week index (0-6), or a Date (used for UTC)
DateProfileGenerator . prototype . isHiddenDay = function ( day ) {
if ( day instanceof Date ) {
day = day . getUTCDay ( ) ;
}
return this . isHiddenDayHash [ day ] ;
} ;
// Incrementing the current day until it is no longer a hidden day, returning a copy.
// DOES NOT CONSIDER validRange!
// If the initial value of `date` is not a hidden day, don't do anything.
// Pass `isExclusive` as `true` if you are dealing with an end date.
// `inc` defaults to `1` (increment one day forward each time)
DateProfileGenerator . prototype . skipHiddenDays = function ( date , inc , isExclusive ) {
if ( inc === void 0 ) { inc = 1 ; }
if ( isExclusive === void 0 ) { isExclusive = false ; }
while ( this . isHiddenDayHash [ ( date . getUTCDay ( ) + ( isExclusive ? inc : 0 ) + 7 ) % 7 ] ) {
date = addDays ( date , inc ) ;
}
return date ;
} ;
return DateProfileGenerator ;
} ( ) ) ;
// TODO: find a way to avoid comparing DateProfiles. it's tedious
function isDateProfilesEqual ( p0 , p1 ) {
return rangesEqual ( p0 . validRange , p1 . validRange ) &&
rangesEqual ( p0 . activeRange , p1 . activeRange ) &&
rangesEqual ( p0 . renderRange , p1 . renderRange ) &&
durationsEqual ( p0 . minTime , p1 . minTime ) &&
durationsEqual ( p0 . maxTime , p1 . maxTime ) ;
/ *
TODO : compare more ?
currentRange : DateRange
currentRangeUnit : string
isRangeAllDay : boolean
isValid : boolean
dateIncrement : Duration
* /
}
function reduce ( state , action , calendar ) {
var viewType = reduceViewType ( state . viewType , action ) ;
var dateProfile = reduceDateProfile ( state . dateProfile , action , state . currentDate , viewType , calendar ) ;
var eventSources = reduceEventSources ( state . eventSources , action , dateProfile , calendar ) ;
var nextState = _ _assign ( { } , state , { viewType : viewType ,
dateProfile : dateProfile , currentDate : reduceCurrentDate ( state . currentDate , action , dateProfile ) , eventSources : eventSources , eventStore : reduceEventStore ( state . eventStore , action , eventSources , dateProfile , calendar ) , dateSelection : reduceDateSelection ( state . dateSelection , action , calendar ) , eventSelection : reduceSelectedEvent ( state . eventSelection , action ) , eventDrag : reduceEventDrag ( state . eventDrag , action , eventSources , calendar ) , eventResize : reduceEventResize ( state . eventResize , action , eventSources , calendar ) , eventSourceLoadingLevel : computeLoadingLevel ( eventSources ) , loadingLevel : computeLoadingLevel ( eventSources ) } ) ;
for ( var _i = 0 , _a = calendar . pluginSystem . hooks . reducers ; _i < _a . length ; _i ++ ) {
var reducerFunc = _a [ _i ] ;
nextState = reducerFunc ( nextState , action , calendar ) ;
}
// console.log(action.type, nextState)
return nextState ;
}
function reduceViewType ( currentViewType , action ) {
switch ( action . type ) {
case 'SET_VIEW_TYPE' :
return action . viewType ;
default :
return currentViewType ;
}
}
function reduceDateProfile ( currentDateProfile , action , currentDate , viewType , calendar ) {
var newDateProfile ;
switch ( action . type ) {
case 'PREV' :
newDateProfile = calendar . dateProfileGenerators [ viewType ] . buildPrev ( currentDateProfile , currentDate ) ;
break ;
case 'NEXT' :
newDateProfile = calendar . dateProfileGenerators [ viewType ] . buildNext ( currentDateProfile , currentDate ) ;
break ;
case 'SET_DATE' :
if ( ! currentDateProfile . activeRange ||
! rangeContainsMarker ( currentDateProfile . currentRange , action . dateMarker ) ) {
newDateProfile = calendar . dateProfileGenerators [ viewType ] . build ( action . dateMarker , undefined , true // forceToValid
) ;
}
break ;
case 'SET_VIEW_TYPE' :
var generator = calendar . dateProfileGenerators [ viewType ] ;
if ( ! generator ) {
throw new Error ( viewType ?
'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' :
'No available FullCalendar view plugins.' ) ;
}
newDateProfile = generator . build ( action . dateMarker || currentDate , undefined , true // forceToValid
) ;
break ;
}
if ( newDateProfile &&
newDateProfile . isValid &&
! ( currentDateProfile && isDateProfilesEqual ( currentDateProfile , newDateProfile ) ) ) {
return newDateProfile ;
}
else {
return currentDateProfile ;
}
}
function reduceCurrentDate ( currentDate , action , dateProfile ) {
switch ( action . type ) {
case 'PREV' :
case 'NEXT' :
if ( ! rangeContainsMarker ( dateProfile . currentRange , currentDate ) ) {
return dateProfile . currentRange . start ;
}
else {
return currentDate ;
}
case 'SET_DATE' :
case 'SET_VIEW_TYPE' :
var newDate = action . dateMarker || currentDate ;
if ( dateProfile . activeRange && ! rangeContainsMarker ( dateProfile . activeRange , newDate ) ) {
return dateProfile . currentRange . start ;
}
else {
return newDate ;
}
default :
return currentDate ;
}
}
function reduceDateSelection ( currentSelection , action , calendar ) {
switch ( action . type ) {
case 'SELECT_DATES' :
return action . selection ;
case 'UNSELECT_DATES' :
return null ;
default :
return currentSelection ;
}
}
function reduceSelectedEvent ( currentInstanceId , action ) {
switch ( action . type ) {
case 'SELECT_EVENT' :
return action . eventInstanceId ;
case 'UNSELECT_EVENT' :
return '' ;
default :
return currentInstanceId ;
}
}
function reduceEventDrag ( currentDrag , action , sources , calendar ) {
switch ( action . type ) {
case 'SET_EVENT_DRAG' :
var newDrag = action . state ;
return {
affectedEvents : newDrag . affectedEvents ,
mutatedEvents : newDrag . mutatedEvents ,
isEvent : newDrag . isEvent ,
origSeg : newDrag . origSeg
} ;
case 'UNSET_EVENT_DRAG' :
return null ;
default :
return currentDrag ;
}
}
function reduceEventResize ( currentResize , action , sources , calendar ) {
switch ( action . type ) {
case 'SET_EVENT_RESIZE' :
var newResize = action . state ;
return {
affectedEvents : newResize . affectedEvents ,
mutatedEvents : newResize . mutatedEvents ,
isEvent : newResize . isEvent ,
origSeg : newResize . origSeg
} ;
case 'UNSET_EVENT_RESIZE' :
return null ;
default :
return currentResize ;
}
}
function computeLoadingLevel ( eventSources ) {
var cnt = 0 ;
for ( var sourceId in eventSources ) {
if ( eventSources [ sourceId ] . isFetching ) {
cnt ++ ;
}
}
return cnt ;
}
var STANDARD _PROPS = {
start : null ,
end : null ,
allDay : Boolean
} ;
function parseDateSpan ( raw , dateEnv , defaultDuration ) {
var span = parseOpenDateSpan ( raw , dateEnv ) ;
var range = span . range ;
if ( ! range . start ) {
return null ;
}
if ( ! range . end ) {
if ( defaultDuration == null ) {
return null ;
}
else {
range . end = dateEnv . add ( range . start , defaultDuration ) ;
}
}
return span ;
}
/ *
TODO : somehow combine with parseRange ?
Will return null if the start / end props were present but parsed invalidly .
* /
function parseOpenDateSpan ( raw , dateEnv ) {
var leftovers = { } ;
var standardProps = refineProps ( raw , STANDARD _PROPS , { } , leftovers ) ;
var startMeta = standardProps . start ? dateEnv . createMarkerMeta ( standardProps . start ) : null ;
var endMeta = standardProps . end ? dateEnv . createMarkerMeta ( standardProps . end ) : null ;
var allDay = standardProps . allDay ;
if ( allDay == null ) {
allDay = ( startMeta && startMeta . isTimeUnspecified ) &&
( ! endMeta || endMeta . isTimeUnspecified ) ;
}
// use this leftover object as the selection object
leftovers . range = {
start : startMeta ? startMeta . marker : null ,
end : endMeta ? endMeta . marker : null
} ;
leftovers . allDay = allDay ;
return leftovers ;
}
function isDateSpansEqual ( span0 , span1 ) {
return rangesEqual ( span0 . range , span1 . range ) &&
span0 . allDay === span1 . allDay &&
isSpanPropsEqual ( span0 , span1 ) ;
}
// the NON-DATE-RELATED props
function isSpanPropsEqual ( span0 , span1 ) {
for ( var propName in span1 ) {
if ( propName !== 'range' && propName !== 'allDay' ) {
if ( span0 [ propName ] !== span1 [ propName ] ) {
return false ;
}
}
}
// are there any props that span0 has that span1 DOESN'T have?
// both have range/allDay, so no need to special-case.
for ( var propName in span0 ) {
if ( ! ( propName in span1 ) ) {
return false ;
}
}
return true ;
}
function buildDateSpanApi ( span , dateEnv ) {
return {
start : dateEnv . toDate ( span . range . start ) ,
end : dateEnv . toDate ( span . range . end ) ,
startStr : dateEnv . formatIso ( span . range . start , { omitTime : span . allDay } ) ,
endStr : dateEnv . formatIso ( span . range . end , { omitTime : span . allDay } ) ,
allDay : span . allDay
} ;
}
function buildDatePointApi ( span , dateEnv ) {
return {
date : dateEnv . toDate ( span . range . start ) ,
dateStr : dateEnv . formatIso ( span . range . start , { omitTime : span . allDay } ) ,
allDay : span . allDay
} ;
}
function fabricateEventRange ( dateSpan , eventUiBases , calendar ) {
var def = parseEventDef ( { editable : false } , '' , // sourceId
dateSpan . allDay , true , // hasEnd
calendar ) ;
return {
def : def ,
ui : compileEventUi ( def , eventUiBases ) ,
instance : createEventInstance ( def . defId , dateSpan . range ) ,
range : dateSpan . range ,
isStart : true ,
isEnd : true
} ;
}
function compileViewDefs ( defaultConfigs , overrideConfigs ) {
var hash = { } ;
var viewType ;
for ( viewType in defaultConfigs ) {
ensureViewDef ( viewType , hash , defaultConfigs , overrideConfigs ) ;
}
for ( viewType in overrideConfigs ) {
ensureViewDef ( viewType , hash , defaultConfigs , overrideConfigs ) ;
}
return hash ;
}
function ensureViewDef ( viewType , hash , defaultConfigs , overrideConfigs ) {
if ( hash [ viewType ] ) {
return hash [ viewType ] ;
}
var viewDef = buildViewDef ( viewType , hash , defaultConfigs , overrideConfigs ) ;
if ( viewDef ) {
hash [ viewType ] = viewDef ;
}
return viewDef ;
}
function buildViewDef ( viewType , hash , defaultConfigs , overrideConfigs ) {
var defaultConfig = defaultConfigs [ viewType ] ;
var overrideConfig = overrideConfigs [ viewType ] ;
var queryProp = function ( name ) {
return ( defaultConfig && defaultConfig [ name ] !== null ) ? defaultConfig [ name ] :
( ( overrideConfig && overrideConfig [ name ] !== null ) ? overrideConfig [ name ] : null ) ;
} ;
var theClass = queryProp ( 'class' ) ;
var superType = queryProp ( 'superType' ) ;
if ( ! superType && theClass ) {
superType =
findViewNameBySubclass ( theClass , overrideConfigs ) ||
findViewNameBySubclass ( theClass , defaultConfigs ) ;
}
var superDef = null ;
if ( superType ) {
if ( superType === viewType ) {
throw new Error ( 'Can\'t have a custom view type that references itself' ) ;
}
superDef = ensureViewDef ( superType , hash , defaultConfigs , overrideConfigs ) ;
}
if ( ! theClass && superDef ) {
theClass = superDef . class ;
}
if ( ! theClass ) {
return null ; // don't throw a warning, might be settings for a single-unit view
}
return {
type : viewType ,
class : theClass ,
defaults : _ _assign ( { } , ( superDef ? superDef . defaults : { } ) , ( defaultConfig ? defaultConfig . options : { } ) ) ,
overrides : _ _assign ( { } , ( superDef ? superDef . overrides : { } ) , ( overrideConfig ? overrideConfig . options : { } ) )
} ;
}
function findViewNameBySubclass ( viewSubclass , configs ) {
var superProto = Object . getPrototypeOf ( viewSubclass . prototype ) ;
for ( var viewType in configs ) {
var parsed = configs [ viewType ] ;
// need DIRECT subclass, so instanceof won't do it
if ( parsed . class && parsed . class . prototype === superProto ) {
return viewType ;
}
}
return '' ;
}
function parseViewConfigs ( inputs ) {
return mapHash ( inputs , parseViewConfig ) ;
}
var VIEW _DEF _PROPS = {
type : String ,
class : null
} ;
function parseViewConfig ( input ) {
if ( typeof input === 'function' ) {
input = { class : input } ;
}
var options = { } ;
var props = refineProps ( input , VIEW _DEF _PROPS , { } , options ) ;
return {
superType : props . type ,
class : props . class ,
options : options
} ;
}
function buildViewSpecs ( defaultInputs , optionsManager ) {
var defaultConfigs = parseViewConfigs ( defaultInputs ) ;
var overrideConfigs = parseViewConfigs ( optionsManager . overrides . views ) ;
var viewDefs = compileViewDefs ( defaultConfigs , overrideConfigs ) ;
return mapHash ( viewDefs , function ( viewDef ) {
return buildViewSpec ( viewDef , overrideConfigs , optionsManager ) ;
} ) ;
}
function buildViewSpec ( viewDef , overrideConfigs , optionsManager ) {
var durationInput = viewDef . overrides . duration ||
viewDef . defaults . duration ||
optionsManager . dynamicOverrides . duration ||
optionsManager . overrides . duration ;
var duration = null ;
var durationUnit = '' ;
var singleUnit = '' ;
var singleUnitOverrides = { } ;
if ( durationInput ) {
duration = createDuration ( durationInput ) ;
if ( duration ) { // valid?
var denom = greatestDurationDenominator ( duration , ! getWeeksFromInput ( durationInput ) ) ;
durationUnit = denom . unit ;
if ( denom . value === 1 ) {
singleUnit = durationUnit ;
singleUnitOverrides = overrideConfigs [ durationUnit ] ? overrideConfigs [ durationUnit ] . options : { } ;
}
}
}
var queryButtonText = function ( options ) {
var buttonTextMap = options . buttonText || { } ;
var buttonTextKey = viewDef . defaults . buttonTextKey ;
if ( buttonTextKey != null && buttonTextMap [ buttonTextKey ] != null ) {
return buttonTextMap [ buttonTextKey ] ;
}
if ( buttonTextMap [ viewDef . type ] != null ) {
return buttonTextMap [ viewDef . type ] ;
}
if ( buttonTextMap [ singleUnit ] != null ) {
return buttonTextMap [ singleUnit ] ;
}
} ;
return {
type : viewDef . type ,
class : viewDef . class ,
duration : duration ,
durationUnit : durationUnit ,
singleUnit : singleUnit ,
options : _ _assign ( { } , globalDefaults , viewDef . defaults , optionsManager . dirDefaults , optionsManager . localeDefaults , optionsManager . overrides , singleUnitOverrides , viewDef . overrides , optionsManager . dynamicOverrides ) ,
buttonTextOverride : queryButtonText ( optionsManager . dynamicOverrides ) ||
queryButtonText ( optionsManager . overrides ) || // constructor-specified buttonText lookup hash takes precedence
viewDef . overrides . buttonText ,
buttonTextDefault : queryButtonText ( optionsManager . localeDefaults ) ||
queryButtonText ( optionsManager . dirDefaults ) ||
viewDef . defaults . buttonText ||
queryButtonText ( globalDefaults ) ||
viewDef . type // fall back to given view name
} ;
}
var Toolbar = /** @class */ ( function ( _super ) {
_ _extends ( Toolbar , _super ) ;
2020-04-01 22:52:43 +00:00
function Toolbar ( extraClassName ) {
var _this = _super . call ( this ) || this ;
2019-08-28 10:59:33 +00:00
_this . _renderLayout = memoizeRendering ( _this . renderLayout , _this . unrenderLayout ) ;
_this . _updateTitle = memoizeRendering ( _this . updateTitle , null , [ _this . _renderLayout ] ) ;
_this . _updateActiveButton = memoizeRendering ( _this . updateActiveButton , null , [ _this . _renderLayout ] ) ;
_this . _updateToday = memoizeRendering ( _this . updateToday , null , [ _this . _renderLayout ] ) ;
_this . _updatePrev = memoizeRendering ( _this . updatePrev , null , [ _this . _renderLayout ] ) ;
_this . _updateNext = memoizeRendering ( _this . updateNext , null , [ _this . _renderLayout ] ) ;
_this . el = createElement ( 'div' , { className : 'fc-toolbar ' + extraClassName } ) ;
return _this ;
}
Toolbar . prototype . destroy = function ( ) {
_super . prototype . destroy . call ( this ) ;
this . _renderLayout . unrender ( ) ; // should unrender everything else
removeElement ( this . el ) ;
} ;
Toolbar . prototype . render = function ( props ) {
this . _renderLayout ( props . layout ) ;
this . _updateTitle ( props . title ) ;
this . _updateActiveButton ( props . activeButton ) ;
this . _updateToday ( props . isTodayEnabled ) ;
this . _updatePrev ( props . isPrevEnabled ) ;
this . _updateNext ( props . isNextEnabled ) ;
} ;
Toolbar . prototype . renderLayout = function ( layout ) {
var el = this . el ;
this . viewsWithButtons = [ ] ;
appendToElement ( el , this . renderSection ( 'left' , layout . left ) ) ;
appendToElement ( el , this . renderSection ( 'center' , layout . center ) ) ;
appendToElement ( el , this . renderSection ( 'right' , layout . right ) ) ;
} ;
Toolbar . prototype . unrenderLayout = function ( ) {
this . el . innerHTML = '' ;
} ;
Toolbar . prototype . renderSection = function ( position , buttonStr ) {
var _this = this ;
2020-04-01 22:52:43 +00:00
var _a = this . context , theme = _a . theme , calendar = _a . calendar ;
2019-08-28 10:59:33 +00:00
var optionsManager = calendar . optionsManager ;
var viewSpecs = calendar . viewSpecs ;
var sectionEl = createElement ( 'div' , { className : 'fc-' + position } ) ;
var calendarCustomButtons = optionsManager . computed . customButtons || { } ;
var calendarButtonTextOverrides = optionsManager . overrides . buttonText || { } ;
var calendarButtonText = optionsManager . computed . buttonText || { } ;
if ( buttonStr ) {
buttonStr . split ( ' ' ) . forEach ( function ( buttonGroupStr , i ) {
var groupChildren = [ ] ;
var isOnlyButtons = true ;
var groupEl ;
buttonGroupStr . split ( ',' ) . forEach ( function ( buttonName , j ) {
var customButtonProps ;
var viewSpec ;
var buttonClick ;
var buttonIcon ; // only one of these will be set
var buttonText ; // "
var buttonInnerHtml ;
var buttonClasses ;
var buttonEl ;
var buttonAriaAttr ;
if ( buttonName === 'title' ) {
groupChildren . push ( htmlToElement ( '<h2> </h2>' ) ) ; // we always want it to take up height
isOnlyButtons = false ;
}
else {
if ( ( customButtonProps = calendarCustomButtons [ buttonName ] ) ) {
buttonClick = function ( ev ) {
if ( customButtonProps . click ) {
customButtonProps . click . call ( buttonEl , ev ) ;
}
} ;
( buttonIcon = theme . getCustomButtonIconClass ( customButtonProps ) ) ||
( buttonIcon = theme . getIconClass ( buttonName ) ) ||
( buttonText = customButtonProps . text ) ;
}
else if ( ( viewSpec = viewSpecs [ buttonName ] ) ) {
_this . viewsWithButtons . push ( buttonName ) ;
buttonClick = function ( ) {
calendar . changeView ( buttonName ) ;
} ;
( buttonText = viewSpec . buttonTextOverride ) ||
( buttonIcon = theme . getIconClass ( buttonName ) ) ||
( buttonText = viewSpec . buttonTextDefault ) ;
}
else if ( calendar [ buttonName ] ) { // a calendar method
buttonClick = function ( ) {
calendar [ buttonName ] ( ) ;
} ;
( buttonText = calendarButtonTextOverrides [ buttonName ] ) ||
( buttonIcon = theme . getIconClass ( buttonName ) ) ||
( buttonText = calendarButtonText [ buttonName ] ) ;
// ^ everything else is considered default
}
if ( buttonClick ) {
buttonClasses = [
'fc-' + buttonName + '-button' ,
theme . getClass ( 'button' )
] ;
if ( buttonText ) {
buttonInnerHtml = htmlEscape ( buttonText ) ;
buttonAriaAttr = '' ;
}
else if ( buttonIcon ) {
buttonInnerHtml = "<span class='" + buttonIcon + "'></span>" ;
buttonAriaAttr = ' aria-label="' + buttonName + '"' ;
}
buttonEl = htmlToElement ( // type="button" so that it doesn't submit a form
'<button type="button" class="' + buttonClasses . join ( ' ' ) + '"' +
buttonAriaAttr +
'>' + buttonInnerHtml + '</button>' ) ;
buttonEl . addEventListener ( 'click' , buttonClick ) ;
groupChildren . push ( buttonEl ) ;
}
}
} ) ;
if ( groupChildren . length > 1 ) {
groupEl = document . createElement ( 'div' ) ;
var buttonGroupClassName = theme . getClass ( 'buttonGroup' ) ;
if ( isOnlyButtons && buttonGroupClassName ) {
groupEl . classList . add ( buttonGroupClassName ) ;
}
appendToElement ( groupEl , groupChildren ) ;
sectionEl . appendChild ( groupEl ) ;
}
else {
appendToElement ( sectionEl , groupChildren ) ; // 1 or 0 children
}
} ) ;
}
return sectionEl ;
} ;
Toolbar . prototype . updateToday = function ( isTodayEnabled ) {
this . toggleButtonEnabled ( 'today' , isTodayEnabled ) ;
} ;
Toolbar . prototype . updatePrev = function ( isPrevEnabled ) {
this . toggleButtonEnabled ( 'prev' , isPrevEnabled ) ;
} ;
Toolbar . prototype . updateNext = function ( isNextEnabled ) {
this . toggleButtonEnabled ( 'next' , isNextEnabled ) ;
} ;
Toolbar . prototype . updateTitle = function ( text ) {
findElements ( this . el , 'h2' ) . forEach ( function ( titleEl ) {
titleEl . innerText = text ;
} ) ;
} ;
Toolbar . prototype . updateActiveButton = function ( buttonName ) {
2020-04-01 22:52:43 +00:00
var theme = this . context . theme ;
var className = theme . getClass ( 'buttonActive' ) ;
2019-08-28 10:59:33 +00:00
findElements ( this . el , 'button' ) . forEach ( function ( buttonEl ) {
if ( buttonName && buttonEl . classList . contains ( 'fc-' + buttonName + '-button' ) ) {
buttonEl . classList . add ( className ) ;
}
else {
buttonEl . classList . remove ( className ) ;
}
} ) ;
} ;
Toolbar . prototype . toggleButtonEnabled = function ( buttonName , bool ) {
findElements ( this . el , '.fc-' + buttonName + '-button' ) . forEach ( function ( buttonEl ) {
buttonEl . disabled = ! bool ;
} ) ;
} ;
return Toolbar ;
} ( Component ) ) ;
var CalendarComponent = /** @class */ ( function ( _super ) {
_ _extends ( CalendarComponent , _super ) ;
2020-04-01 22:52:43 +00:00
function CalendarComponent ( el ) {
var _this = _super . call ( this ) || this ;
_this . elClassNames = [ ] ;
_this . renderSkeleton = memoizeRendering ( _this . _renderSkeleton , _this . _unrenderSkeleton ) ;
_this . renderToolbars = memoizeRendering ( _this . _renderToolbars , _this . _unrenderToolbars , [ _this . renderSkeleton ] ) ;
_this . buildComponentContext = memoize ( buildComponentContext ) ;
2019-08-28 10:59:33 +00:00
_this . buildViewPropTransformers = memoize ( buildViewPropTransformers ) ;
_this . el = el ;
_this . computeTitle = memoize ( computeTitle ) ;
_this . parseBusinessHours = memoize ( function ( input ) {
2020-04-01 22:52:43 +00:00
return parseBusinessHours ( input , _this . context . calendar ) ;
2019-08-28 10:59:33 +00:00
} ) ;
return _this ;
}
2020-04-01 22:52:43 +00:00
CalendarComponent . prototype . render = function ( props , context ) {
this . freezeHeight ( ) ;
var title = this . computeTitle ( props . dateProfile , props . viewSpec . options ) ;
this . renderSkeleton ( context ) ;
this . renderToolbars ( props . viewSpec , props . dateProfile , props . currentDate , title ) ;
this . renderView ( props , title ) ;
this . updateSize ( ) ;
this . thawHeight ( ) ;
} ;
2019-08-28 10:59:33 +00:00
CalendarComponent . prototype . destroy = function ( ) {
if ( this . header ) {
this . header . destroy ( ) ;
}
if ( this . footer ) {
this . footer . destroy ( ) ;
}
2020-04-01 22:52:43 +00:00
this . renderSkeleton . unrender ( ) ; // will call destroyView
_super . prototype . destroy . call ( this ) ;
} ;
CalendarComponent . prototype . _renderSkeleton = function ( context ) {
this . updateElClassNames ( context ) ;
prependToElement ( this . el , this . contentEl = createElement ( 'div' , { className : 'fc-view-container' } ) ) ;
var calendar = context . calendar ;
for ( var _i = 0 , _a = calendar . pluginSystem . hooks . viewContainerModifiers ; _i < _a . length ; _i ++ ) {
var modifyViewContainer = _a [ _i ] ;
modifyViewContainer ( this . contentEl , calendar ) ;
}
} ;
CalendarComponent . prototype . _unrenderSkeleton = function ( ) {
// weird to have this here
2019-08-28 10:59:33 +00:00
if ( this . view ) {
2020-04-01 22:52:43 +00:00
this . savedScroll = this . view . queryScroll ( ) ;
2019-08-28 10:59:33 +00:00
this . view . destroy ( ) ;
2020-04-01 22:52:43 +00:00
this . view = null ;
2019-08-28 10:59:33 +00:00
}
removeElement ( this . contentEl ) ;
2020-04-01 22:52:43 +00:00
this . removeElClassNames ( ) ;
2019-08-28 10:59:33 +00:00
} ;
2020-04-01 22:52:43 +00:00
CalendarComponent . prototype . removeElClassNames = function ( ) {
2019-08-28 10:59:33 +00:00
var classList = this . el . classList ;
2020-04-01 22:52:43 +00:00
for ( var _i = 0 , _a = this . elClassNames ; _i < _a . length ; _i ++ ) {
var className = _a [ _i ] ;
classList . remove ( className ) ;
}
this . elClassNames = [ ] ;
} ;
CalendarComponent . prototype . updateElClassNames = function ( context ) {
this . removeElClassNames ( ) ;
var theme = context . theme , options = context . options ;
this . elClassNames = [
'fc' ,
'fc-' + options . dir ,
theme . getClass ( 'widget' )
] ;
var classList = this . el . classList ;
for ( var _i = 0 , _a = this . elClassNames ; _i < _a . length ; _i ++ ) {
var className = _a [ _i ] ;
classList . add ( className ) ;
}
} ;
CalendarComponent . prototype . _renderToolbars = function ( viewSpec , dateProfile , currentDate , title ) {
var _a = this , context = _a . context , header = _a . header , footer = _a . footer ;
var options = context . options , calendar = context . calendar ;
var headerLayout = options . header ;
var footerLayout = options . footer ;
var dateProfileGenerator = this . props . dateProfileGenerator ;
var now = calendar . getNow ( ) ;
2019-08-28 10:59:33 +00:00
var todayInfo = dateProfileGenerator . build ( now ) ;
var prevInfo = dateProfileGenerator . buildPrev ( dateProfile , currentDate ) ;
var nextInfo = dateProfileGenerator . buildNext ( dateProfile , currentDate ) ;
var toolbarProps = {
title : title ,
activeButton : viewSpec . type ,
isTodayEnabled : todayInfo . isValid && ! rangeContainsMarker ( dateProfile . currentRange , now ) ,
isPrevEnabled : prevInfo . isValid ,
isNextEnabled : nextInfo . isValid
} ;
if ( headerLayout ) {
2020-04-01 22:52:43 +00:00
if ( ! header ) {
header = this . header = new Toolbar ( 'fc-header-toolbar' ) ;
prependToElement ( this . el , header . el ) ;
2019-08-28 10:59:33 +00:00
}
2020-04-01 22:52:43 +00:00
header . receiveProps ( _ _assign ( { layout : headerLayout } , toolbarProps ) , context ) ;
2019-08-28 10:59:33 +00:00
}
2020-04-01 22:52:43 +00:00
else if ( header ) {
header . destroy ( ) ;
header = this . header = null ;
2019-08-28 10:59:33 +00:00
}
if ( footerLayout ) {
2020-04-01 22:52:43 +00:00
if ( ! footer ) {
footer = this . footer = new Toolbar ( 'fc-footer-toolbar' ) ;
appendToElement ( this . el , footer . el ) ;
2019-08-28 10:59:33 +00:00
}
2020-04-01 22:52:43 +00:00
footer . receiveProps ( _ _assign ( { layout : footerLayout } , toolbarProps ) , context ) ;
}
else if ( footer ) {
footer . destroy ( ) ;
footer = this . footer = null ;
}
} ;
CalendarComponent . prototype . _unrenderToolbars = function ( ) {
if ( this . header ) {
this . header . destroy ( ) ;
this . header = null ;
2019-08-28 10:59:33 +00:00
}
2020-04-01 22:52:43 +00:00
if ( this . footer ) {
2019-08-28 10:59:33 +00:00
this . footer . destroy ( ) ;
this . footer = null ;
}
} ;
CalendarComponent . prototype . renderView = function ( props , title ) {
var view = this . view ;
2020-04-01 22:52:43 +00:00
var _a = this . context , calendar = _a . calendar , options = _a . options ;
2019-08-28 10:59:33 +00:00
var viewSpec = props . viewSpec , dateProfileGenerator = props . dateProfileGenerator ;
if ( ! view || view . viewSpec !== viewSpec ) {
if ( view ) {
view . destroy ( ) ;
}
2020-04-01 22:52:43 +00:00
view = this . view = new viewSpec [ 'class' ] ( viewSpec , this . contentEl ) ;
if ( this . savedScroll ) {
view . addScroll ( this . savedScroll , true ) ;
this . savedScroll = null ;
}
2019-08-28 10:59:33 +00:00
}
view . title = title ; // for the API
var viewProps = {
2020-04-01 22:52:43 +00:00
dateProfileGenerator : dateProfileGenerator ,
2019-08-28 10:59:33 +00:00
dateProfile : props . dateProfile ,
businessHours : this . parseBusinessHours ( viewSpec . options . businessHours ) ,
eventStore : props . eventStore ,
eventUiBases : props . eventUiBases ,
dateSelection : props . dateSelection ,
eventSelection : props . eventSelection ,
eventDrag : props . eventDrag ,
eventResize : props . eventResize
} ;
2020-04-01 22:52:43 +00:00
var transformers = this . buildViewPropTransformers ( calendar . pluginSystem . hooks . viewPropsTransformers ) ;
2019-08-28 10:59:33 +00:00
for ( var _i = 0 , transformers _1 = transformers ; _i < transformers _1 . length ; _i ++ ) {
var transformer = transformers _1 [ _i ] ;
2020-04-01 22:52:43 +00:00
_ _assign ( viewProps , transformer . transform ( viewProps , viewSpec , props , options ) ) ;
2019-08-28 10:59:33 +00:00
}
2020-04-01 22:52:43 +00:00
view . receiveProps ( viewProps , this . buildComponentContext ( this . context , viewSpec , view ) ) ;
2019-08-28 10:59:33 +00:00
} ;
// Sizing
// -----------------------------------------------------------------------------------------------------------------
CalendarComponent . prototype . updateSize = function ( isResize ) {
if ( isResize === void 0 ) { isResize = false ; }
var view = this . view ;
2020-04-01 22:52:43 +00:00
if ( ! view ) {
return ; // why?
2019-08-28 10:59:33 +00:00
}
if ( isResize || this . isHeightAuto == null ) {
this . computeHeightVars ( ) ;
}
view . updateSize ( isResize , this . viewHeight , this . isHeightAuto ) ;
view . updateNowIndicator ( ) ; // we need to guarantee this will run after updateSize
view . popScroll ( isResize ) ;
} ;
CalendarComponent . prototype . computeHeightVars = function ( ) {
2020-04-01 22:52:43 +00:00
var calendar = this . context . calendar ; // yuck. need to handle dynamic options
2019-08-28 10:59:33 +00:00
var heightInput = calendar . opt ( 'height' ) ;
var contentHeightInput = calendar . opt ( 'contentHeight' ) ;
this . isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto' ;
if ( typeof contentHeightInput === 'number' ) { // exists and not 'auto'
this . viewHeight = contentHeightInput ;
}
else if ( typeof contentHeightInput === 'function' ) { // exists and is a function
this . viewHeight = contentHeightInput ( ) ;
}
else if ( typeof heightInput === 'number' ) { // exists and not 'auto'
this . viewHeight = heightInput - this . queryToolbarsHeight ( ) ;
}
else if ( typeof heightInput === 'function' ) { // exists and is a function
this . viewHeight = heightInput ( ) - this . queryToolbarsHeight ( ) ;
}
else if ( heightInput === 'parent' ) { // set to height of parent element
var parentEl = this . el . parentNode ;
this . viewHeight = parentEl . getBoundingClientRect ( ) . height - this . queryToolbarsHeight ( ) ;
}
else {
this . viewHeight = Math . round ( this . contentEl . getBoundingClientRect ( ) . width /
Math . max ( calendar . opt ( 'aspectRatio' ) , . 5 ) ) ;
}
} ;
CalendarComponent . prototype . queryToolbarsHeight = function ( ) {
var height = 0 ;
if ( this . header ) {
height += computeHeightAndMargins ( this . header . el ) ;
}
if ( this . footer ) {
height += computeHeightAndMargins ( this . footer . el ) ;
}
return height ;
} ;
// Height "Freezing"
// -----------------------------------------------------------------------------------------------------------------
CalendarComponent . prototype . freezeHeight = function ( ) {
applyStyle ( this . el , {
height : this . el . getBoundingClientRect ( ) . height ,
overflow : 'hidden'
} ) ;
} ;
CalendarComponent . prototype . thawHeight = function ( ) {
applyStyle ( this . el , {
height : '' ,
overflow : ''
} ) ;
} ;
return CalendarComponent ;
} ( Component ) ) ;
// Title and Date Formatting
// -----------------------------------------------------------------------------------------------------------------
// Computes what the title at the top of the calendar should be for this view
function computeTitle ( dateProfile , viewOptions ) {
var range ;
// for views that span a large unit of time, show the proper interval, ignoring stray days before and after
if ( /^(year|month)$/ . test ( dateProfile . currentRangeUnit ) ) {
range = dateProfile . currentRange ;
}
else { // for day units or smaller, use the actual day range
range = dateProfile . activeRange ;
}
2020-04-01 22:52:43 +00:00
return this . context . dateEnv . formatRange ( range . start , range . end , createFormatter ( viewOptions . titleFormat || computeTitleFormat ( dateProfile ) , viewOptions . titleRangeSeparator ) , { isEndExclusive : dateProfile . isRangeAllDay } ) ;
2019-08-28 10:59:33 +00:00
}
// Generates the format string that should be used to generate the title for the current date range.
// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
function computeTitleFormat ( dateProfile ) {
var currentRangeUnit = dateProfile . currentRangeUnit ;
if ( currentRangeUnit === 'year' ) {
return { year : 'numeric' } ;
}
else if ( currentRangeUnit === 'month' ) {
return { year : 'numeric' , month : 'long' } ; // like "September 2014"
}
else {
var days = diffWholeDays ( dateProfile . currentRange . start , dateProfile . currentRange . end ) ;
if ( days !== null && days > 1 ) {
// multi-day range. shorter, like "Sep 9 - 10 2014"
return { year : 'numeric' , month : 'short' , day : 'numeric' } ;
}
else {
// one day. longer, like "September 9 2014"
return { year : 'numeric' , month : 'long' , day : 'numeric' } ;
}
}
}
2020-04-01 22:52:43 +00:00
// build a context scoped to the view
function buildComponentContext ( context , viewSpec , view ) {
return context . extend ( viewSpec . options , view ) ;
}
2019-08-28 10:59:33 +00:00
// Plugin
// -----------------------------------------------------------------------------------------------------------------
function buildViewPropTransformers ( theClasses ) {
return theClasses . map ( function ( theClass ) {
return new theClass ( ) ;
} ) ;
}
var Interaction = /** @class */ ( function ( ) {
function Interaction ( settings ) {
this . component = settings . component ;
}
Interaction . prototype . destroy = function ( ) {
} ;
return Interaction ;
} ( ) ) ;
function parseInteractionSettings ( component , input ) {
return {
component : component ,
el : input . el ,
useEventCenter : input . useEventCenter != null ? input . useEventCenter : true
} ;
}
function interactionSettingsToStore ( settings ) {
var _a ;
return _a = { } ,
_a [ settings . component . uid ] = settings ,
_a ;
}
// global state
var interactionSettingsStore = { } ;
/ *
Detects when the user clicks on an event within a DateComponent
* /
var EventClicking = /** @class */ ( function ( _super ) {
_ _extends ( EventClicking , _super ) ;
function EventClicking ( settings ) {
var _this = _super . call ( this , settings ) || this ;
_this . handleSegClick = function ( ev , segEl ) {
var component = _this . component ;
2020-04-01 22:52:43 +00:00
var _a = component . context , calendar = _a . calendar , view = _a . view ;
2019-08-28 10:59:33 +00:00
var seg = getElSeg ( segEl ) ;
if ( seg && // might be the <div> surrounding the more link
component . isValidSegDownEl ( ev . target ) ) {
// our way to simulate a link click for elements that can't be <a> tags
// grab before trigger fired in case trigger trashes DOM thru rerendering
var hasUrlContainer = elementClosest ( ev . target , '.fc-has-url' ) ;
var url = hasUrlContainer ? hasUrlContainer . querySelector ( 'a[href]' ) . href : '' ;
2020-04-01 22:52:43 +00:00
calendar . publiclyTrigger ( 'eventClick' , [
2019-08-28 10:59:33 +00:00
{
el : segEl ,
2020-04-01 22:52:43 +00:00
event : new EventApi ( component . context . calendar , seg . eventRange . def , seg . eventRange . instance ) ,
2019-08-28 10:59:33 +00:00
jsEvent : ev ,
2020-04-01 22:52:43 +00:00
view : view
2019-08-28 10:59:33 +00:00
}
] ) ;
if ( url && ! ev . defaultPrevented ) {
window . location . href = url ;
}
}
} ;
var component = settings . component ;
_this . destroy = listenBySelector ( component . el , 'click' , component . fgSegSelector + ',' + component . bgSegSelector , _this . handleSegClick ) ;
return _this ;
}
return EventClicking ;
} ( Interaction ) ) ;
/ *
Triggers events and adds / removes core classNames when the user ' s pointer
enters / leaves event - elements of a component .
* /
var EventHovering = /** @class */ ( function ( _super ) {
_ _extends ( EventHovering , _super ) ;
function EventHovering ( settings ) {
var _this = _super . call ( this , settings ) || this ;
// for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
_this . handleEventElRemove = function ( el ) {
if ( el === _this . currentSegEl ) {
_this . handleSegLeave ( null , _this . currentSegEl ) ;
}
} ;
_this . handleSegEnter = function ( ev , segEl ) {
if ( getElSeg ( segEl ) ) { // TODO: better way to make sure not hovering over more+ link or its wrapper
segEl . classList . add ( 'fc-allow-mouse-resize' ) ;
_this . currentSegEl = segEl ;
_this . triggerEvent ( 'eventMouseEnter' , ev , segEl ) ;
}
} ;
_this . handleSegLeave = function ( ev , segEl ) {
if ( _this . currentSegEl ) {
segEl . classList . remove ( 'fc-allow-mouse-resize' ) ;
_this . currentSegEl = null ;
_this . triggerEvent ( 'eventMouseLeave' , ev , segEl ) ;
}
} ;
var component = settings . component ;
_this . removeHoverListeners = listenToHoverBySelector ( component . el , component . fgSegSelector + ',' + component . bgSegSelector , _this . handleSegEnter , _this . handleSegLeave ) ;
2020-04-01 22:52:43 +00:00
// how to make sure component already has context?
component . context . calendar . on ( 'eventElRemove' , _this . handleEventElRemove ) ;
2019-08-28 10:59:33 +00:00
return _this ;
}
EventHovering . prototype . destroy = function ( ) {
this . removeHoverListeners ( ) ;
2020-04-01 22:52:43 +00:00
this . component . context . calendar . off ( 'eventElRemove' , this . handleEventElRemove ) ;
2019-08-28 10:59:33 +00:00
} ;
EventHovering . prototype . triggerEvent = function ( publicEvName , ev , segEl ) {
var component = this . component ;
2020-04-01 22:52:43 +00:00
var _a = component . context , calendar = _a . calendar , view = _a . view ;
2019-08-28 10:59:33 +00:00
var seg = getElSeg ( segEl ) ;
if ( ! ev || component . isValidSegDownEl ( ev . target ) ) {
2020-04-01 22:52:43 +00:00
calendar . publiclyTrigger ( publicEvName , [
2019-08-28 10:59:33 +00:00
{
el : segEl ,
2020-04-01 22:52:43 +00:00
event : new EventApi ( calendar , seg . eventRange . def , seg . eventRange . instance ) ,
2019-08-28 10:59:33 +00:00
jsEvent : ev ,
2020-04-01 22:52:43 +00:00
view : view
2019-08-28 10:59:33 +00:00
}
] ) ;
}
} ;
return EventHovering ;
} ( Interaction ) ) ;
var StandardTheme = /** @class */ ( function ( _super ) {
_ _extends ( StandardTheme , _super ) ;
function StandardTheme ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
return StandardTheme ;
} ( Theme ) ) ;
StandardTheme . prototype . classes = {
widget : 'fc-unthemed' ,
widgetHeader : 'fc-widget-header' ,
widgetContent : 'fc-widget-content' ,
buttonGroup : 'fc-button-group' ,
button : 'fc-button fc-button-primary' ,
buttonActive : 'fc-button-active' ,
popoverHeader : 'fc-widget-header' ,
popoverContent : 'fc-widget-content' ,
// day grid
headerRow : 'fc-widget-header' ,
dayRow : 'fc-widget-content' ,
// list view
listView : 'fc-widget-content'
} ;
StandardTheme . prototype . baseIconClass = 'fc-icon' ;
StandardTheme . prototype . iconClasses = {
close : 'fc-icon-x' ,
prev : 'fc-icon-chevron-left' ,
next : 'fc-icon-chevron-right' ,
prevYear : 'fc-icon-chevrons-left' ,
nextYear : 'fc-icon-chevrons-right'
} ;
StandardTheme . prototype . iconOverrideOption = 'buttonIcons' ;
StandardTheme . prototype . iconOverrideCustomButtonOption = 'icon' ;
StandardTheme . prototype . iconOverridePrefix = 'fc-icon-' ;
var Calendar = /** @class */ ( function ( ) {
function Calendar ( el , overrides ) {
var _this = this ;
2020-04-01 22:52:43 +00:00
this . buildComponentContext = memoize ( buildComponentContext$1 ) ;
2019-08-28 10:59:33 +00:00
this . parseRawLocales = memoize ( parseRawLocales ) ;
this . buildLocale = memoize ( buildLocale ) ;
this . buildDateEnv = memoize ( buildDateEnv ) ;
this . buildTheme = memoize ( buildTheme ) ;
this . buildEventUiSingleBase = memoize ( this . _buildEventUiSingleBase ) ;
this . buildSelectionConfig = memoize ( this . _buildSelectionConfig ) ;
this . buildEventUiBySource = memoizeOutput ( buildEventUiBySource , isPropsEqual ) ;
this . buildEventUiBases = memoize ( buildEventUiBases ) ;
this . interactionsStore = { } ;
this . actionQueue = [ ] ;
this . isReducing = false ;
// isDisplaying: boolean = false // installed in DOM? accepting renders?
this . needsRerender = false ; // needs a render?
this . isRendering = false ; // currently in the executeRender function?
this . renderingPauseDepth = 0 ;
this . buildDelayedRerender = memoize ( buildDelayedRerender ) ;
this . afterSizingTriggers = { } ;
this . isViewUpdated = false ;
this . isDatesUpdated = false ;
this . isEventsUpdated = false ;
this . el = el ;
this . optionsManager = new OptionsManager ( overrides || { } ) ;
this . pluginSystem = new PluginSystem ( ) ;
// only do once. don't do in handleOptions. because can't remove plugins
this . addPluginInputs ( this . optionsManager . computed . plugins || [ ] ) ;
this . handleOptions ( this . optionsManager . computed ) ;
this . publiclyTrigger ( '_init' ) ; // for tests
this . hydrate ( ) ;
this . calendarInteractions = this . pluginSystem . hooks . calendarInteractions
. map ( function ( calendarInteractionClass ) {
return new calendarInteractionClass ( _this ) ;
} ) ;
}
Calendar . prototype . addPluginInputs = function ( pluginInputs ) {
var pluginDefs = refinePluginDefs ( pluginInputs ) ;
for ( var _i = 0 , pluginDefs _1 = pluginDefs ; _i < pluginDefs _1 . length ; _i ++ ) {
var pluginDef = pluginDefs _1 [ _i ] ;
this . pluginSystem . add ( pluginDef ) ;
}
} ;
Object . defineProperty ( Calendar . prototype , "view" , {
// public API
get : function ( ) {
return this . component ? this . component . view : null ;
} ,
enumerable : true ,
configurable : true
} ) ;
// Public API for rendering
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . render = function ( ) {
if ( ! this . component ) {
2020-04-01 22:52:43 +00:00
this . component = new CalendarComponent ( this . el ) ;
2019-08-28 10:59:33 +00:00
this . renderableEventStore = createEmptyEventStore ( ) ;
this . bindHandlers ( ) ;
this . executeRender ( ) ;
}
else {
2020-04-01 22:52:43 +00:00
this . requestRerender ( ) ;
2019-08-28 10:59:33 +00:00
}
} ;
Calendar . prototype . destroy = function ( ) {
if ( this . component ) {
this . unbindHandlers ( ) ;
this . component . destroy ( ) ; // don't null-out. in case API needs access
this . component = null ; // umm ???
for ( var _i = 0 , _a = this . calendarInteractions ; _i < _a . length ; _i ++ ) {
var interaction = _a [ _i ] ;
interaction . destroy ( ) ;
}
this . publiclyTrigger ( '_destroyed' ) ;
}
} ;
// Handlers
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . bindHandlers = function ( ) {
var _this = this ;
// event delegation for nav links
this . removeNavLinkListener = listenBySelector ( this . el , 'click' , 'a[data-goto]' , function ( ev , anchorEl ) {
var gotoOptions = anchorEl . getAttribute ( 'data-goto' ) ;
gotoOptions = gotoOptions ? JSON . parse ( gotoOptions ) : { } ;
var dateEnv = _this . dateEnv ;
var dateMarker = dateEnv . createMarker ( gotoOptions . date ) ;
var viewType = gotoOptions . type ;
// property like "navLinkDayClick". might be a string or a function
var customAction = _this . viewOpt ( 'navLink' + capitaliseFirstLetter ( viewType ) + 'Click' ) ;
if ( typeof customAction === 'function' ) {
customAction ( dateEnv . toDate ( dateMarker ) , ev ) ;
}
else {
if ( typeof customAction === 'string' ) {
viewType = customAction ;
}
_this . zoomTo ( dateMarker , viewType ) ;
}
} ) ;
if ( this . opt ( 'handleWindowResize' ) ) {
window . addEventListener ( 'resize' , this . windowResizeProxy = debounce ( // prevents rapid calls
this . windowResize . bind ( this ) , this . opt ( 'windowResizeDelay' ) ) ) ;
}
} ;
Calendar . prototype . unbindHandlers = function ( ) {
this . removeNavLinkListener ( ) ;
if ( this . windowResizeProxy ) {
window . removeEventListener ( 'resize' , this . windowResizeProxy ) ;
this . windowResizeProxy = null ;
}
} ;
// Dispatcher
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . hydrate = function ( ) {
var _this = this ;
this . state = this . buildInitialState ( ) ;
var rawSources = this . opt ( 'eventSources' ) || [ ] ;
var singleRawSource = this . opt ( 'events' ) ;
var sources = [ ] ; // parsed
if ( singleRawSource ) {
rawSources . unshift ( singleRawSource ) ;
}
for ( var _i = 0 , rawSources _1 = rawSources ; _i < rawSources _1 . length ; _i ++ ) {
var rawSource = rawSources _1 [ _i ] ;
var source = parseEventSource ( rawSource , this ) ;
if ( source ) {
sources . push ( source ) ;
}
}
this . batchRendering ( function ( ) {
_this . dispatch ( { type : 'INIT' } ) ; // pass in sources here?
_this . dispatch ( { type : 'ADD_EVENT_SOURCES' , sources : sources } ) ;
_this . dispatch ( {
type : 'SET_VIEW_TYPE' ,
viewType : _this . opt ( 'defaultView' ) || _this . pluginSystem . hooks . defaultView
} ) ;
} ) ;
} ;
Calendar . prototype . buildInitialState = function ( ) {
return {
viewType : null ,
loadingLevel : 0 ,
eventSourceLoadingLevel : 0 ,
currentDate : this . getInitialDate ( ) ,
dateProfile : null ,
eventSources : { } ,
eventStore : createEmptyEventStore ( ) ,
dateSelection : null ,
eventSelection : '' ,
eventDrag : null ,
eventResize : null
} ;
} ;
Calendar . prototype . dispatch = function ( action ) {
this . actionQueue . push ( action ) ;
if ( ! this . isReducing ) {
this . isReducing = true ;
var oldState = this . state ;
while ( this . actionQueue . length ) {
this . state = this . reduce ( this . state , this . actionQueue . shift ( ) , this ) ;
}
var newState = this . state ;
this . isReducing = false ;
if ( ! oldState . loadingLevel && newState . loadingLevel ) {
this . publiclyTrigger ( 'loading' , [ true ] ) ;
}
else if ( oldState . loadingLevel && ! newState . loadingLevel ) {
this . publiclyTrigger ( 'loading' , [ false ] ) ;
}
var view = this . component && this . component . view ;
2020-04-01 22:52:43 +00:00
if ( oldState . eventStore !== newState . eventStore ) {
2019-08-28 10:59:33 +00:00
if ( oldState . eventStore ) {
this . isEventsUpdated = true ;
}
}
2020-04-01 22:52:43 +00:00
if ( oldState . dateProfile !== newState . dateProfile ) {
2019-08-28 10:59:33 +00:00
if ( oldState . dateProfile && view ) { // why would view be null!?
this . publiclyTrigger ( 'datesDestroy' , [
{
view : view ,
el : view . el
}
] ) ;
}
this . isDatesUpdated = true ;
}
2020-04-01 22:52:43 +00:00
if ( oldState . viewType !== newState . viewType ) {
2019-08-28 10:59:33 +00:00
if ( oldState . viewType && view ) { // why would view be null!?
this . publiclyTrigger ( 'viewSkeletonDestroy' , [
{
view : view ,
el : view . el
}
] ) ;
}
this . isViewUpdated = true ;
}
this . requestRerender ( ) ;
}
} ;
Calendar . prototype . reduce = function ( state , action , calendar ) {
return reduce ( state , action , calendar ) ;
} ;
// Render Queue
// -----------------------------------------------------------------------------------------------------------------
2020-04-01 22:52:43 +00:00
Calendar . prototype . requestRerender = function ( ) {
2019-08-28 10:59:33 +00:00
this . needsRerender = true ;
this . delayedRerender ( ) ; // will call a debounced-version of tryRerender
} ;
Calendar . prototype . tryRerender = function ( ) {
if ( this . component && // must be accepting renders
this . needsRerender && // indicates that a rerender was requested
! this . renderingPauseDepth && // not paused
! this . isRendering // not currently in the render loop
) {
this . executeRender ( ) ;
}
} ;
Calendar . prototype . batchRendering = function ( func ) {
this . renderingPauseDepth ++ ;
func ( ) ;
this . renderingPauseDepth -- ;
if ( this . needsRerender ) {
this . requestRerender ( ) ;
}
} ;
// Rendering
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . executeRender = function ( ) {
// clear these BEFORE the render so that new values will accumulate during render
this . needsRerender = false ;
this . isRendering = true ;
2020-04-01 22:52:43 +00:00
this . renderComponent ( ) ;
2019-08-28 10:59:33 +00:00
this . isRendering = false ;
// received a rerender request while rendering
if ( this . needsRerender ) {
this . delayedRerender ( ) ;
}
} ;
/ *
don ' t call this directly . use executeRender instead
* /
2020-04-01 22:52:43 +00:00
Calendar . prototype . renderComponent = function ( ) {
2019-08-28 10:59:33 +00:00
var _a = this , state = _a . state , component = _a . component ;
var viewType = state . viewType ;
var viewSpec = this . viewSpecs [ viewType ] ;
if ( ! viewSpec ) {
throw new Error ( "View type \"" + viewType + "\" is not valid" ) ;
}
// if event sources are still loading and progressive rendering hasn't been enabled,
// keep rendering the last fully loaded set of events
var renderableEventStore = this . renderableEventStore =
( state . eventSourceLoadingLevel && ! this . opt ( 'progressiveEventRendering' ) ) ?
this . renderableEventStore :
state . eventStore ;
var eventUiSingleBase = this . buildEventUiSingleBase ( viewSpec . options ) ;
var eventUiBySource = this . buildEventUiBySource ( state . eventSources ) ;
var eventUiBases = this . eventUiBases = this . buildEventUiBases ( renderableEventStore . defs , eventUiSingleBase , eventUiBySource ) ;
2020-04-01 22:52:43 +00:00
component . receiveProps ( _ _assign ( { } , state , { viewSpec : viewSpec , dateProfileGenerator : this . dateProfileGenerators [ viewType ] , dateProfile : state . dateProfile , eventStore : renderableEventStore , eventUiBases : eventUiBases , dateSelection : state . dateSelection , eventSelection : state . eventSelection , eventDrag : state . eventDrag , eventResize : state . eventResize } ) , this . buildComponentContext ( this . theme , this . dateEnv , this . optionsManager . computed ) ) ;
2019-08-28 10:59:33 +00:00
if ( this . isViewUpdated ) {
this . isViewUpdated = false ;
this . publiclyTrigger ( 'viewSkeletonRender' , [
{
view : component . view ,
el : component . view . el
}
] ) ;
}
if ( this . isDatesUpdated ) {
this . isDatesUpdated = false ;
this . publiclyTrigger ( 'datesRender' , [
{
view : component . view ,
el : component . view . el
}
] ) ;
}
if ( this . isEventsUpdated ) {
this . isEventsUpdated = false ;
}
this . releaseAfterSizingTriggers ( ) ;
} ;
// Options
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . setOption = function ( name , val ) {
var _a ;
this . mutateOptions ( ( _a = { } , _a [ name ] = val , _a ) , [ ] , true ) ;
} ;
Calendar . prototype . getOption = function ( name ) {
return this . optionsManager . computed [ name ] ;
} ;
Calendar . prototype . opt = function ( name ) {
return this . optionsManager . computed [ name ] ;
} ;
Calendar . prototype . viewOpt = function ( name ) {
return this . viewOpts ( ) [ name ] ;
} ;
Calendar . prototype . viewOpts = function ( ) {
return this . viewSpecs [ this . state . viewType ] . options ;
} ;
/ *
handles option changes ( like a diff )
* /
Calendar . prototype . mutateOptions = function ( updates , removals , isDynamic , deepEqual ) {
var _this = this ;
var changeHandlers = this . pluginSystem . hooks . optionChangeHandlers ;
var normalUpdates = { } ;
var specialUpdates = { } ;
var oldDateEnv = this . dateEnv ; // do this before handleOptions
var isTimeZoneDirty = false ;
var isSizeDirty = false ;
var anyDifficultOptions = Boolean ( removals . length ) ;
for ( var name _1 in updates ) {
if ( changeHandlers [ name _1 ] ) {
specialUpdates [ name _1 ] = updates [ name _1 ] ;
}
else {
normalUpdates [ name _1 ] = updates [ name _1 ] ;
}
}
for ( var name _2 in normalUpdates ) {
if ( /^(height|contentHeight|aspectRatio)$/ . test ( name _2 ) ) {
isSizeDirty = true ;
}
else if ( /^(defaultDate|defaultView)$/ . test ( name _2 ) ) ;
else {
anyDifficultOptions = true ;
if ( name _2 === 'timeZone' ) {
isTimeZoneDirty = true ;
}
}
}
this . optionsManager . mutate ( normalUpdates , removals , isDynamic ) ;
if ( anyDifficultOptions ) {
this . handleOptions ( this . optionsManager . computed ) ;
}
this . batchRendering ( function ( ) {
if ( anyDifficultOptions ) {
if ( isTimeZoneDirty ) {
_this . dispatch ( {
type : 'CHANGE_TIMEZONE' ,
oldDateEnv : oldDateEnv
} ) ;
}
/ * H A C K
2020-04-01 22:52:43 +00:00
has the same effect as calling this . requestRerender ( )
2019-08-28 10:59:33 +00:00
but recomputes the state ' s dateProfile
* /
_this . dispatch ( {
type : 'SET_VIEW_TYPE' ,
viewType : _this . state . viewType
} ) ;
}
else if ( isSizeDirty ) {
_this . updateSize ( ) ;
}
// special updates
if ( deepEqual ) {
for ( var name _3 in specialUpdates ) {
changeHandlers [ name _3 ] ( specialUpdates [ name _3 ] , _this , deepEqual ) ;
}
}
} ) ;
} ;
/ *
rebuilds things based off of a complete set of refined options
* /
Calendar . prototype . handleOptions = function ( options ) {
var _this = this ;
var pluginHooks = this . pluginSystem . hooks ;
this . defaultAllDayEventDuration = createDuration ( options . defaultAllDayEventDuration ) ;
this . defaultTimedEventDuration = createDuration ( options . defaultTimedEventDuration ) ;
this . delayedRerender = this . buildDelayedRerender ( options . rerenderDelay ) ;
this . theme = this . buildTheme ( options ) ;
var available = this . parseRawLocales ( options . locales ) ;
this . availableRawLocales = available . map ;
var locale = this . buildLocale ( options . locale || available . defaultCode , available . map ) ;
this . dateEnv = this . buildDateEnv ( locale , options . timeZone , pluginHooks . namedTimeZonedImpl , options . firstDay , options . weekNumberCalculation , options . weekLabel , pluginHooks . cmdFormatter ) ;
this . selectionConfig = this . buildSelectionConfig ( options ) ; // needs dateEnv. do after :(
// ineffecient to do every time?
this . viewSpecs = buildViewSpecs ( pluginHooks . views , this . optionsManager ) ;
// ineffecient to do every time?
this . dateProfileGenerators = mapHash ( this . viewSpecs , function ( viewSpec ) {
return new viewSpec . class . prototype . dateProfileGeneratorClass ( viewSpec , _this ) ;
} ) ;
} ;
Calendar . prototype . getAvailableLocaleCodes = function ( ) {
return Object . keys ( this . availableRawLocales ) ;
} ;
Calendar . prototype . _buildSelectionConfig = function ( rawOpts ) {
return processScopedUiProps ( 'select' , rawOpts , this ) ;
} ;
Calendar . prototype . _buildEventUiSingleBase = function ( rawOpts ) {
if ( rawOpts . editable ) { // so 'editable' affected events
rawOpts = _ _assign ( { } , rawOpts , { eventEditable : true } ) ;
}
return processScopedUiProps ( 'event' , rawOpts , this ) ;
} ;
// Trigger
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . hasPublicHandlers = function ( name ) {
return this . hasHandlers ( name ) ||
this . opt ( name ) ; // handler specified in options
} ;
Calendar . prototype . publiclyTrigger = function ( name , args ) {
var optHandler = this . opt ( name ) ;
this . triggerWith ( name , this , args ) ;
if ( optHandler ) {
return optHandler . apply ( this , args ) ;
}
} ;
Calendar . prototype . publiclyTriggerAfterSizing = function ( name , args ) {
var afterSizingTriggers = this . afterSizingTriggers ;
( afterSizingTriggers [ name ] || ( afterSizingTriggers [ name ] = [ ] ) ) . push ( args ) ;
} ;
Calendar . prototype . releaseAfterSizingTriggers = function ( ) {
var afterSizingTriggers = this . afterSizingTriggers ;
for ( var name _4 in afterSizingTriggers ) {
for ( var _i = 0 , _a = afterSizingTriggers [ name _4 ] ; _i < _a . length ; _i ++ ) {
var args = _a [ _i ] ;
this . publiclyTrigger ( name _4 , args ) ;
}
}
this . afterSizingTriggers = { } ;
} ;
// View
// -----------------------------------------------------------------------------------------------------------------
// Returns a boolean about whether the view is okay to instantiate at some point
Calendar . prototype . isValidViewType = function ( viewType ) {
return Boolean ( this . viewSpecs [ viewType ] ) ;
} ;
Calendar . prototype . changeView = function ( viewType , dateOrRange ) {
var dateMarker = null ;
if ( dateOrRange ) {
if ( dateOrRange . start && dateOrRange . end ) { // a range
this . optionsManager . mutate ( { visibleRange : dateOrRange } , [ ] ) ; // will not rerender
this . handleOptions ( this . optionsManager . computed ) ; // ...but yuck
}
else { // a date
dateMarker = this . dateEnv . createMarker ( dateOrRange ) ; // just like gotoDate
}
}
this . unselect ( ) ;
this . dispatch ( {
type : 'SET_VIEW_TYPE' ,
viewType : viewType ,
dateMarker : dateMarker
} ) ;
} ;
// Forces navigation to a view for the given date.
// `viewType` can be a specific view name or a generic one like "week" or "day".
// needs to change
Calendar . prototype . zoomTo = function ( dateMarker , viewType ) {
var spec ;
viewType = viewType || 'day' ; // day is default zoom
spec = this . viewSpecs [ viewType ] ||
this . getUnitViewSpec ( viewType ) ;
this . unselect ( ) ;
if ( spec ) {
this . dispatch ( {
type : 'SET_VIEW_TYPE' ,
viewType : spec . type ,
dateMarker : dateMarker
} ) ;
}
else {
this . dispatch ( {
type : 'SET_DATE' ,
dateMarker : dateMarker
} ) ;
}
} ;
// Given a duration singular unit, like "week" or "day", finds a matching view spec.
// Preference is given to views that have corresponding buttons.
Calendar . prototype . getUnitViewSpec = function ( unit ) {
var component = this . component ;
var viewTypes = [ ] ;
var i ;
var spec ;
// put views that have buttons first. there will be duplicates, but oh
if ( component . header ) {
viewTypes . push . apply ( viewTypes , component . header . viewsWithButtons ) ;
}
if ( component . footer ) {
viewTypes . push . apply ( viewTypes , component . footer . viewsWithButtons ) ;
}
for ( var viewType in this . viewSpecs ) {
viewTypes . push ( viewType ) ;
}
for ( i = 0 ; i < viewTypes . length ; i ++ ) {
spec = this . viewSpecs [ viewTypes [ i ] ] ;
if ( spec ) {
if ( spec . singleUnit === unit ) {
return spec ;
}
}
}
} ;
// Current Date
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . getInitialDate = function ( ) {
var defaultDateInput = this . opt ( 'defaultDate' ) ;
// compute the initial ambig-timezone date
if ( defaultDateInput != null ) {
return this . dateEnv . createMarker ( defaultDateInput ) ;
}
else {
return this . getNow ( ) ; // getNow already returns unzoned
}
} ;
Calendar . prototype . prev = function ( ) {
this . unselect ( ) ;
this . dispatch ( { type : 'PREV' } ) ;
} ;
Calendar . prototype . next = function ( ) {
this . unselect ( ) ;
this . dispatch ( { type : 'NEXT' } ) ;
} ;
Calendar . prototype . prevYear = function ( ) {
this . unselect ( ) ;
this . dispatch ( {
type : 'SET_DATE' ,
dateMarker : this . dateEnv . addYears ( this . state . currentDate , - 1 )
} ) ;
} ;
Calendar . prototype . nextYear = function ( ) {
this . unselect ( ) ;
this . dispatch ( {
type : 'SET_DATE' ,
dateMarker : this . dateEnv . addYears ( this . state . currentDate , 1 )
} ) ;
} ;
Calendar . prototype . today = function ( ) {
this . unselect ( ) ;
this . dispatch ( {
type : 'SET_DATE' ,
dateMarker : this . getNow ( )
} ) ;
} ;
Calendar . prototype . gotoDate = function ( zonedDateInput ) {
this . unselect ( ) ;
this . dispatch ( {
type : 'SET_DATE' ,
dateMarker : this . dateEnv . createMarker ( zonedDateInput )
} ) ;
} ;
Calendar . prototype . incrementDate = function ( deltaInput ) {
var delta = createDuration ( deltaInput ) ;
if ( delta ) { // else, warn about invalid input?
this . unselect ( ) ;
this . dispatch ( {
type : 'SET_DATE' ,
dateMarker : this . dateEnv . add ( this . state . currentDate , delta )
} ) ;
}
} ;
// for external API
Calendar . prototype . getDate = function ( ) {
return this . dateEnv . toDate ( this . state . currentDate ) ;
} ;
// Date Formatting Utils
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . formatDate = function ( d , formatter ) {
var dateEnv = this . dateEnv ;
return dateEnv . format ( dateEnv . createMarker ( d ) , createFormatter ( formatter ) ) ;
} ;
// `settings` is for formatter AND isEndExclusive
Calendar . prototype . formatRange = function ( d0 , d1 , settings ) {
var dateEnv = this . dateEnv ;
return dateEnv . formatRange ( dateEnv . createMarker ( d0 ) , dateEnv . createMarker ( d1 ) , createFormatter ( settings , this . opt ( 'defaultRangeSeparator' ) ) , settings ) ;
} ;
Calendar . prototype . formatIso = function ( d , omitTime ) {
var dateEnv = this . dateEnv ;
return dateEnv . formatIso ( dateEnv . createMarker ( d ) , { omitTime : omitTime } ) ;
} ;
// Sizing
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . windowResize = function ( ev ) {
if ( ! this . isHandlingWindowResize &&
this . component && // why?
ev . target === window // not a jqui resize event
) {
this . isHandlingWindowResize = true ;
this . updateSize ( ) ;
this . publiclyTrigger ( 'windowResize' , [ this . view ] ) ;
this . isHandlingWindowResize = false ;
}
} ;
Calendar . prototype . updateSize = function ( ) {
if ( this . component ) { // when?
this . component . updateSize ( true ) ;
}
} ;
// Component Registration
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . registerInteractiveComponent = function ( component , settingsInput ) {
var settings = parseInteractionSettings ( component , settingsInput ) ;
var DEFAULT _INTERACTIONS = [
EventClicking ,
EventHovering
] ;
var interactionClasses = DEFAULT _INTERACTIONS . concat ( this . pluginSystem . hooks . componentInteractions ) ;
var interactions = interactionClasses . map ( function ( interactionClass ) {
return new interactionClass ( settings ) ;
} ) ;
this . interactionsStore [ component . uid ] = interactions ;
interactionSettingsStore [ component . uid ] = settings ;
} ;
Calendar . prototype . unregisterInteractiveComponent = function ( component ) {
for ( var _i = 0 , _a = this . interactionsStore [ component . uid ] ; _i < _a . length ; _i ++ ) {
var listener = _a [ _i ] ;
listener . destroy ( ) ;
}
delete this . interactionsStore [ component . uid ] ;
delete interactionSettingsStore [ component . uid ] ;
} ;
// Date Selection / Event Selection / DayClick
// -----------------------------------------------------------------------------------------------------------------
// this public method receives start/end dates in any format, with any timezone
// NOTE: args were changed from v3
Calendar . prototype . select = function ( dateOrObj , endDate ) {
var selectionInput ;
if ( endDate == null ) {
if ( dateOrObj . start != null ) {
selectionInput = dateOrObj ;
}
else {
selectionInput = {
start : dateOrObj ,
end : null
} ;
}
}
else {
selectionInput = {
start : dateOrObj ,
end : endDate
} ;
}
var selection = parseDateSpan ( selectionInput , this . dateEnv , createDuration ( { days : 1 } ) // TODO: cache this?
) ;
if ( selection ) { // throw parse error otherwise?
this . dispatch ( { type : 'SELECT_DATES' , selection : selection } ) ;
this . triggerDateSelect ( selection ) ;
}
} ;
// public method
Calendar . prototype . unselect = function ( pev ) {
if ( this . state . dateSelection ) {
this . dispatch ( { type : 'UNSELECT_DATES' } ) ;
this . triggerDateUnselect ( pev ) ;
}
} ;
Calendar . prototype . triggerDateSelect = function ( selection , pev ) {
var arg = _ _assign ( { } , this . buildDateSpanApi ( selection ) , { jsEvent : pev ? pev . origEvent : null , view : this . view } ) ;
this . publiclyTrigger ( 'select' , [ arg ] ) ;
} ;
Calendar . prototype . triggerDateUnselect = function ( pev ) {
this . publiclyTrigger ( 'unselect' , [
{
jsEvent : pev ? pev . origEvent : null ,
view : this . view
}
] ) ;
} ;
// TODO: receive pev?
Calendar . prototype . triggerDateClick = function ( dateSpan , dayEl , view , ev ) {
var arg = _ _assign ( { } , this . buildDatePointApi ( dateSpan ) , { dayEl : dayEl , jsEvent : ev , // Is this always a mouse event? See #4655
view : view } ) ;
this . publiclyTrigger ( 'dateClick' , [ arg ] ) ;
} ;
Calendar . prototype . buildDatePointApi = function ( dateSpan ) {
var props = { } ;
for ( var _i = 0 , _a = this . pluginSystem . hooks . datePointTransforms ; _i < _a . length ; _i ++ ) {
var transform = _a [ _i ] ;
_ _assign ( props , transform ( dateSpan , this ) ) ;
}
_ _assign ( props , buildDatePointApi ( dateSpan , this . dateEnv ) ) ;
return props ;
} ;
Calendar . prototype . buildDateSpanApi = function ( dateSpan ) {
var props = { } ;
for ( var _i = 0 , _a = this . pluginSystem . hooks . dateSpanTransforms ; _i < _a . length ; _i ++ ) {
var transform = _a [ _i ] ;
_ _assign ( props , transform ( dateSpan , this ) ) ;
}
_ _assign ( props , buildDateSpanApi ( dateSpan , this . dateEnv ) ) ;
return props ;
} ;
// Date Utils
// -----------------------------------------------------------------------------------------------------------------
// Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option
Calendar . prototype . getNow = function ( ) {
var now = this . opt ( 'now' ) ;
if ( typeof now === 'function' ) {
now = now ( ) ;
}
if ( now == null ) {
return this . dateEnv . createNowMarker ( ) ;
}
return this . dateEnv . createMarker ( now ) ;
} ;
// Event-Date Utilities
// -----------------------------------------------------------------------------------------------------------------
// Given an event's allDay status and start date, return what its fallback end date should be.
// TODO: rename to computeDefaultEventEnd
Calendar . prototype . getDefaultEventEnd = function ( allDay , marker ) {
var end = marker ;
if ( allDay ) {
end = startOfDay ( end ) ;
end = this . dateEnv . add ( end , this . defaultAllDayEventDuration ) ;
}
else {
end = this . dateEnv . add ( end , this . defaultTimedEventDuration ) ;
}
return end ;
} ;
// Public Events API
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . addEvent = function ( eventInput , sourceInput ) {
if ( eventInput instanceof EventApi ) {
var def = eventInput . _def ;
var instance = eventInput . _instance ;
// not already present? don't want to add an old snapshot
if ( ! this . state . eventStore . defs [ def . defId ] ) {
this . dispatch ( {
type : 'ADD_EVENTS' ,
eventStore : eventTupleToStore ( { def : def , instance : instance } ) // TODO: better util for two args?
} ) ;
}
return eventInput ;
}
var sourceId ;
if ( sourceInput instanceof EventSourceApi ) {
sourceId = sourceInput . internalEventSource . sourceId ;
}
else if ( sourceInput != null ) {
var sourceApi = this . getEventSourceById ( sourceInput ) ; // TODO: use an internal function
if ( ! sourceApi ) {
console . warn ( 'Could not find an event source with ID "' + sourceInput + '"' ) ; // TODO: test
return null ;
}
else {
sourceId = sourceApi . internalEventSource . sourceId ;
}
}
var tuple = parseEvent ( eventInput , sourceId , this ) ;
if ( tuple ) {
this . dispatch ( {
type : 'ADD_EVENTS' ,
eventStore : eventTupleToStore ( tuple )
} ) ;
return new EventApi ( this , tuple . def , tuple . def . recurringDef ? null : tuple . instance ) ;
}
return null ;
} ;
// TODO: optimize
Calendar . prototype . getEventById = function ( id ) {
var _a = this . state . eventStore , defs = _a . defs , instances = _a . instances ;
id = String ( id ) ;
for ( var defId in defs ) {
var def = defs [ defId ] ;
if ( def . publicId === id ) {
if ( def . recurringDef ) {
return new EventApi ( this , def , null ) ;
}
else {
for ( var instanceId in instances ) {
var instance = instances [ instanceId ] ;
if ( instance . defId === def . defId ) {
return new EventApi ( this , def , instance ) ;
}
}
}
}
}
return null ;
} ;
Calendar . prototype . getEvents = function ( ) {
var _a = this . state . eventStore , defs = _a . defs , instances = _a . instances ;
var eventApis = [ ] ;
for ( var id in instances ) {
var instance = instances [ id ] ;
var def = defs [ instance . defId ] ;
eventApis . push ( new EventApi ( this , def , instance ) ) ;
}
return eventApis ;
} ;
Calendar . prototype . removeAllEvents = function ( ) {
this . dispatch ( { type : 'REMOVE_ALL_EVENTS' } ) ;
} ;
Calendar . prototype . rerenderEvents = function ( ) {
this . dispatch ( { type : 'RESET_EVENTS' } ) ;
} ;
// Public Event Sources API
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . getEventSources = function ( ) {
var sourceHash = this . state . eventSources ;
var sourceApis = [ ] ;
for ( var internalId in sourceHash ) {
sourceApis . push ( new EventSourceApi ( this , sourceHash [ internalId ] ) ) ;
}
return sourceApis ;
} ;
Calendar . prototype . getEventSourceById = function ( id ) {
var sourceHash = this . state . eventSources ;
id = String ( id ) ;
for ( var sourceId in sourceHash ) {
if ( sourceHash [ sourceId ] . publicId === id ) {
return new EventSourceApi ( this , sourceHash [ sourceId ] ) ;
}
}
return null ;
} ;
Calendar . prototype . addEventSource = function ( sourceInput ) {
if ( sourceInput instanceof EventSourceApi ) {
// not already present? don't want to add an old snapshot
if ( ! this . state . eventSources [ sourceInput . internalEventSource . sourceId ] ) {
this . dispatch ( {
type : 'ADD_EVENT_SOURCES' ,
sources : [ sourceInput . internalEventSource ]
} ) ;
}
return sourceInput ;
}
var eventSource = parseEventSource ( sourceInput , this ) ;
if ( eventSource ) { // TODO: error otherwise?
this . dispatch ( { type : 'ADD_EVENT_SOURCES' , sources : [ eventSource ] } ) ;
return new EventSourceApi ( this , eventSource ) ;
}
return null ;
} ;
Calendar . prototype . removeAllEventSources = function ( ) {
this . dispatch ( { type : 'REMOVE_ALL_EVENT_SOURCES' } ) ;
} ;
Calendar . prototype . refetchEvents = function ( ) {
this . dispatch ( { type : 'FETCH_EVENT_SOURCES' } ) ;
} ;
// Scroll
// -----------------------------------------------------------------------------------------------------------------
Calendar . prototype . scrollToTime = function ( timeInput ) {
var duration = createDuration ( timeInput ) ;
if ( duration ) {
this . component . view . scrollToDuration ( duration ) ;
}
} ;
return Calendar ;
} ( ) ) ;
EmitterMixin . mixInto ( Calendar ) ;
// for memoizers
// -----------------------------------------------------------------------------------------------------------------
2020-04-01 22:52:43 +00:00
function buildComponentContext$1 ( theme , dateEnv , options ) {
return new ComponentContext ( this , theme , dateEnv , options , null ) ;
}
2019-08-28 10:59:33 +00:00
function buildDateEnv ( locale , timeZone , namedTimeZoneImpl , firstDay , weekNumberCalculation , weekLabel , cmdFormatter ) {
return new DateEnv ( {
calendarSystem : 'gregory' ,
timeZone : timeZone ,
namedTimeZoneImpl : namedTimeZoneImpl ,
locale : locale ,
weekNumberCalculation : weekNumberCalculation ,
firstDay : firstDay ,
weekLabel : weekLabel ,
cmdFormatter : cmdFormatter
} ) ;
}
function buildTheme ( calendarOptions ) {
var themeClass = this . pluginSystem . hooks . themeClasses [ calendarOptions . themeSystem ] || StandardTheme ;
return new themeClass ( calendarOptions ) ;
}
function buildDelayedRerender ( wait ) {
var func = this . tryRerender . bind ( this ) ;
if ( wait != null ) {
func = debounce ( func , wait ) ;
}
return func ;
}
function buildEventUiBySource ( eventSources ) {
return mapHash ( eventSources , function ( eventSource ) {
return eventSource . ui ;
} ) ;
}
function buildEventUiBases ( eventDefs , eventUiSingleBase , eventUiBySource ) {
var eventUiBases = { '' : eventUiSingleBase } ;
for ( var defId in eventDefs ) {
var def = eventDefs [ defId ] ;
if ( def . sourceId && eventUiBySource [ def . sourceId ] ) {
eventUiBases [ defId ] = eventUiBySource [ def . sourceId ] ;
}
}
return eventUiBases ;
}
var View = /** @class */ ( function ( _super ) {
_ _extends ( View , _super ) ;
2020-04-01 22:52:43 +00:00
function View ( viewSpec , parentEl ) {
var _this = _super . call ( this , createElement ( 'div' , { className : 'fc-view fc-' + viewSpec . type + '-view' } ) ) || this ;
2019-08-28 10:59:33 +00:00
_this . renderDatesMem = memoizeRendering ( _this . renderDatesWrap , _this . unrenderDatesWrap ) ;
_this . renderBusinessHoursMem = memoizeRendering ( _this . renderBusinessHours , _this . unrenderBusinessHours , [ _this . renderDatesMem ] ) ;
_this . renderDateSelectionMem = memoizeRendering ( _this . renderDateSelectionWrap , _this . unrenderDateSelectionWrap , [ _this . renderDatesMem ] ) ;
_this . renderEventsMem = memoizeRendering ( _this . renderEvents , _this . unrenderEvents , [ _this . renderDatesMem ] ) ;
_this . renderEventSelectionMem = memoizeRendering ( _this . renderEventSelectionWrap , _this . unrenderEventSelectionWrap , [ _this . renderEventsMem ] ) ;
_this . renderEventDragMem = memoizeRendering ( _this . renderEventDragWrap , _this . unrenderEventDragWrap , [ _this . renderDatesMem ] ) ;
_this . renderEventResizeMem = memoizeRendering ( _this . renderEventResizeWrap , _this . unrenderEventResizeWrap , [ _this . renderDatesMem ] ) ;
_this . viewSpec = viewSpec ;
_this . type = viewSpec . type ;
parentEl . appendChild ( _this . el ) ;
_this . initialize ( ) ;
return _this ;
}
View . prototype . initialize = function ( ) {
} ;
Object . defineProperty ( View . prototype , "activeStart" , {
// Date Setting/Unsetting
// -----------------------------------------------------------------------------------------------------------------
get : function ( ) {
2020-04-01 22:52:43 +00:00
return this . context . dateEnv . toDate ( this . props . dateProfile . activeRange . start ) ;
2019-08-28 10:59:33 +00:00
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( View . prototype , "activeEnd" , {
get : function ( ) {
2020-04-01 22:52:43 +00:00
return this . context . dateEnv . toDate ( this . props . dateProfile . activeRange . end ) ;
2019-08-28 10:59:33 +00:00
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( View . prototype , "currentStart" , {
get : function ( ) {
2020-04-01 22:52:43 +00:00
return this . context . dateEnv . toDate ( this . props . dateProfile . currentRange . start ) ;
2019-08-28 10:59:33 +00:00
} ,
enumerable : true ,
configurable : true
} ) ;
Object . defineProperty ( View . prototype , "currentEnd" , {
get : function ( ) {
2020-04-01 22:52:43 +00:00
return this . context . dateEnv . toDate ( this . props . dateProfile . currentRange . end ) ;
2019-08-28 10:59:33 +00:00
} ,
enumerable : true ,
configurable : true
} ) ;
// General Rendering
// -----------------------------------------------------------------------------------------------------------------
2020-04-01 22:52:43 +00:00
View . prototype . render = function ( props , context ) {
2019-08-28 10:59:33 +00:00
this . renderDatesMem ( props . dateProfile ) ;
this . renderBusinessHoursMem ( props . businessHours ) ;
this . renderDateSelectionMem ( props . dateSelection ) ;
this . renderEventsMem ( props . eventStore ) ;
this . renderEventSelectionMem ( props . eventSelection ) ;
this . renderEventDragMem ( props . eventDrag ) ;
this . renderEventResizeMem ( props . eventResize ) ;
} ;
2020-04-01 22:52:43 +00:00
View . prototype . beforeUpdate = function ( ) {
this . addScroll ( this . queryScroll ( ) ) ;
} ;
2019-08-28 10:59:33 +00:00
View . prototype . destroy = function ( ) {
_super . prototype . destroy . call ( this ) ;
this . renderDatesMem . unrender ( ) ; // should unrender everything else
} ;
// Sizing
// -----------------------------------------------------------------------------------------------------------------
View . prototype . updateSize = function ( isResize , viewHeight , isAuto ) {
2020-04-01 22:52:43 +00:00
var calendar = this . context . calendar ;
if ( isResize ) {
this . addScroll ( this . queryScroll ( ) ) ; // NOTE: same code as in beforeUpdate
}
2019-08-28 10:59:33 +00:00
if ( isResize || // HACKS...
calendar . isViewUpdated ||
calendar . isDatesUpdated ||
calendar . isEventsUpdated ) {
// sort of the catch-all sizing
// anything that might cause dimension changes
this . updateBaseSize ( isResize , viewHeight , isAuto ) ;
}
2020-04-01 22:52:43 +00:00
// NOTE: popScroll is called by CalendarComponent
2019-08-28 10:59:33 +00:00
} ;
View . prototype . updateBaseSize = function ( isResize , viewHeight , isAuto ) {
} ;
// Date Rendering
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderDatesWrap = function ( dateProfile ) {
this . renderDates ( dateProfile ) ;
this . addScroll ( {
2020-04-01 22:52:43 +00:00
duration : createDuration ( this . context . options . scrollTime )
2019-08-28 10:59:33 +00:00
} ) ;
} ;
View . prototype . unrenderDatesWrap = function ( ) {
this . stopNowIndicator ( ) ;
this . unrenderDates ( ) ;
} ;
View . prototype . renderDates = function ( dateProfile ) { } ;
View . prototype . unrenderDates = function ( ) { } ;
// Business Hours
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderBusinessHours = function ( businessHours ) { } ;
View . prototype . unrenderBusinessHours = function ( ) { } ;
// Date Selection
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderDateSelectionWrap = function ( selection ) {
if ( selection ) {
this . renderDateSelection ( selection ) ;
}
} ;
View . prototype . unrenderDateSelectionWrap = function ( selection ) {
if ( selection ) {
this . unrenderDateSelection ( selection ) ;
}
} ;
View . prototype . renderDateSelection = function ( selection ) { } ;
View . prototype . unrenderDateSelection = function ( selection ) { } ;
// Event Rendering
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderEvents = function ( eventStore ) { } ;
View . prototype . unrenderEvents = function ( ) { } ;
// util for subclasses
View . prototype . sliceEvents = function ( eventStore , allDay ) {
var props = this . props ;
2020-04-01 22:52:43 +00:00
return sliceEventStore ( eventStore , props . eventUiBases , props . dateProfile . activeRange , allDay ? this . context . nextDayThreshold : null ) . fg ;
2019-08-28 10:59:33 +00:00
} ;
// Event Selection
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderEventSelectionWrap = function ( instanceId ) {
if ( instanceId ) {
this . renderEventSelection ( instanceId ) ;
}
} ;
View . prototype . unrenderEventSelectionWrap = function ( instanceId ) {
if ( instanceId ) {
this . unrenderEventSelection ( instanceId ) ;
}
} ;
View . prototype . renderEventSelection = function ( instanceId ) { } ;
View . prototype . unrenderEventSelection = function ( instanceId ) { } ;
// Event Drag
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderEventDragWrap = function ( state ) {
if ( state ) {
this . renderEventDrag ( state ) ;
}
} ;
View . prototype . unrenderEventDragWrap = function ( state ) {
if ( state ) {
this . unrenderEventDrag ( state ) ;
}
} ;
View . prototype . renderEventDrag = function ( state ) { } ;
View . prototype . unrenderEventDrag = function ( state ) { } ;
// Event Resize
// -----------------------------------------------------------------------------------------------------------------
View . prototype . renderEventResizeWrap = function ( state ) {
if ( state ) {
this . renderEventResize ( state ) ;
}
} ;
View . prototype . unrenderEventResizeWrap = function ( state ) {
if ( state ) {
this . unrenderEventResize ( state ) ;
}
} ;
View . prototype . renderEventResize = function ( state ) { } ;
View . prototype . unrenderEventResize = function ( state ) { } ;
/ * N o w I n d i c a t o r
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
// Immediately render the current time indicator and begins re-rendering it at an interval,
// which is defined by this.getNowIndicatorUnit().
// TODO: somehow do this for the current whole day's background too
2020-04-01 22:52:43 +00:00
// USAGE: must be called manually from subclasses' render methods! don't need to call stopNowIndicator tho
View . prototype . startNowIndicator = function ( dateProfile , dateProfileGenerator ) {
2019-08-28 10:59:33 +00:00
var _this = this ;
2020-04-01 22:52:43 +00:00
var _a = this . context , calendar = _a . calendar , dateEnv = _a . dateEnv , options = _a . options ;
2019-08-28 10:59:33 +00:00
var unit ;
var update ;
var delay ; // ms wait value
2020-04-01 22:52:43 +00:00
if ( options . nowIndicator && ! this . initialNowDate ) {
unit = this . getNowIndicatorUnit ( dateProfile , dateProfileGenerator ) ;
2019-08-28 10:59:33 +00:00
if ( unit ) {
update = this . updateNowIndicator . bind ( this ) ;
2020-04-01 22:52:43 +00:00
this . initialNowDate = calendar . getNow ( ) ;
2019-08-28 10:59:33 +00:00
this . initialNowQueriedMs = new Date ( ) . valueOf ( ) ;
// wait until the beginning of the next interval
delay = dateEnv . add ( dateEnv . startOf ( this . initialNowDate , unit ) , createDuration ( 1 , unit ) ) . valueOf ( ) - this . initialNowDate . valueOf ( ) ;
// TODO: maybe always use setTimeout, waiting until start of next unit
this . nowIndicatorTimeoutID = setTimeout ( function ( ) {
_this . nowIndicatorTimeoutID = null ;
update ( ) ;
if ( unit === 'second' ) {
delay = 1000 ; // every second
}
else {
delay = 1000 * 60 ; // otherwise, every minute
}
_this . nowIndicatorIntervalID = setInterval ( update , delay ) ; // update every interval
} , delay ) ;
}
// rendering will be initiated in updateSize
}
} ;
// rerenders the now indicator, computing the new current time from the amount of time that has passed
// since the initial getNow call.
View . prototype . updateNowIndicator = function ( ) {
if ( this . props . dateProfile && // a way to determine if dates were rendered yet
this . initialNowDate // activated before?
) {
this . unrenderNowIndicator ( ) ; // won't unrender if unnecessary
this . renderNowIndicator ( addMs ( this . initialNowDate , new Date ( ) . valueOf ( ) - this . initialNowQueriedMs ) ) ;
this . isNowIndicatorRendered = true ;
}
} ;
// Immediately unrenders the view's current time indicator and stops any re-rendering timers.
// Won't cause side effects if indicator isn't rendered.
View . prototype . stopNowIndicator = function ( ) {
2020-04-01 22:52:43 +00:00
if ( this . nowIndicatorTimeoutID ) {
clearTimeout ( this . nowIndicatorTimeoutID ) ;
this . nowIndicatorTimeoutID = null ;
}
if ( this . nowIndicatorIntervalID ) {
clearInterval ( this . nowIndicatorIntervalID ) ;
this . nowIndicatorIntervalID = null ;
}
2019-08-28 10:59:33 +00:00
if ( this . isNowIndicatorRendered ) {
this . unrenderNowIndicator ( ) ;
this . isNowIndicatorRendered = false ;
}
} ;
2020-04-01 22:52:43 +00:00
View . prototype . getNowIndicatorUnit = function ( dateProfile , dateProfileGenerator ) {
2019-08-28 10:59:33 +00:00
// subclasses should implement
} ;
// Renders a current time indicator at the given datetime
View . prototype . renderNowIndicator = function ( date ) {
// SUBCLASSES MUST PASS TO CHILDREN!
} ;
// Undoes the rendering actions from renderNowIndicator
View . prototype . unrenderNowIndicator = function ( ) {
// SUBCLASSES MUST PASS TO CHILDREN!
} ;
/ * S c r o l l e r
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
2020-04-01 22:52:43 +00:00
View . prototype . addScroll = function ( scroll , isForced ) {
if ( isForced ) {
scroll . isForced = isForced ;
}
_ _assign ( this . queuedScroll || ( this . queuedScroll = { } ) , scroll ) ;
2019-08-28 10:59:33 +00:00
} ;
View . prototype . popScroll = function ( isResize ) {
this . applyQueuedScroll ( isResize ) ;
this . queuedScroll = null ;
} ;
View . prototype . applyQueuedScroll = function ( isResize ) {
2020-04-01 22:52:43 +00:00
if ( this . queuedScroll ) {
this . applyScroll ( this . queuedScroll , isResize ) ;
}
2019-08-28 10:59:33 +00:00
} ;
View . prototype . queryScroll = function ( ) {
var scroll = { } ;
if ( this . props . dateProfile ) { // dates rendered yet?
_ _assign ( scroll , this . queryDateScroll ( ) ) ;
}
return scroll ;
} ;
View . prototype . applyScroll = function ( scroll , isResize ) {
2020-04-01 22:52:43 +00:00
var duration = scroll . duration , isForced = scroll . isForced ;
if ( duration != null && ! isForced ) {
2019-08-28 10:59:33 +00:00
delete scroll . duration ;
if ( this . props . dateProfile ) { // dates rendered yet?
_ _assign ( scroll , this . computeDateScroll ( duration ) ) ;
}
}
if ( this . props . dateProfile ) { // dates rendered yet?
this . applyDateScroll ( scroll ) ;
}
} ;
View . prototype . computeDateScroll = function ( duration ) {
return { } ; // subclasses must implement
} ;
View . prototype . queryDateScroll = function ( ) {
return { } ; // subclasses must implement
} ;
View . prototype . applyDateScroll = function ( scroll ) {
// subclasses must implement
} ;
// for API
View . prototype . scrollToDuration = function ( duration ) {
this . applyScroll ( { duration : duration } , false ) ;
} ;
return View ;
} ( DateComponent ) ) ;
EmitterMixin . mixInto ( View ) ;
View . prototype . usesMinMaxTime = false ;
View . prototype . dateProfileGeneratorClass = DateProfileGenerator ;
var FgEventRenderer = /** @class */ ( function ( ) {
2020-04-01 22:52:43 +00:00
function FgEventRenderer ( ) {
2019-08-28 10:59:33 +00:00
this . segs = [ ] ;
this . isSizeDirty = false ;
}
2020-04-01 22:52:43 +00:00
FgEventRenderer . prototype . renderSegs = function ( context , segs , mirrorInfo ) {
this . context = context ;
2019-08-28 10:59:33 +00:00
this . rangeUpdated ( ) ; // called too frequently :(
// render an `.el` on each seg
// returns a subset of the segs. segs that were actually rendered
segs = this . renderSegEls ( segs , mirrorInfo ) ;
this . segs = segs ;
this . attachSegs ( segs , mirrorInfo ) ;
this . isSizeDirty = true ;
2020-04-01 22:52:43 +00:00
triggerRenderedSegs ( this . context , this . segs , Boolean ( mirrorInfo ) ) ;
2019-08-28 10:59:33 +00:00
} ;
2020-04-01 22:52:43 +00:00
FgEventRenderer . prototype . unrender = function ( context , _segs , mirrorInfo ) {
triggerWillRemoveSegs ( this . context , this . segs , Boolean ( mirrorInfo ) ) ;
2019-08-28 10:59:33 +00:00
this . detachSegs ( this . segs ) ;
this . segs = [ ] ;
} ;
// Updates values that rely on options and also relate to range
FgEventRenderer . prototype . rangeUpdated = function ( ) {
var options = this . context . options ;
var displayEventTime ;
var displayEventEnd ;
this . eventTimeFormat = createFormatter ( options . eventTimeFormat || this . computeEventTimeFormat ( ) , options . defaultRangeSeparator ) ;
displayEventTime = options . displayEventTime ;
if ( displayEventTime == null ) {
displayEventTime = this . computeDisplayEventTime ( ) ; // might be based off of range
}
displayEventEnd = options . displayEventEnd ;
if ( displayEventEnd == null ) {
displayEventEnd = this . computeDisplayEventEnd ( ) ; // might be based off of range
}
this . displayEventTime = displayEventTime ;
this . displayEventEnd = displayEventEnd ;
} ;
// Renders and assigns an `el` property for each foreground event segment.
// Only returns segments that successfully rendered.
FgEventRenderer . prototype . renderSegEls = function ( segs , mirrorInfo ) {
var html = '' ;
var i ;
if ( segs . length ) { // don't build an empty html string
// build a large concatenation of event segment HTML
for ( i = 0 ; i < segs . length ; i ++ ) {
html += this . renderSegHtml ( segs [ i ] , mirrorInfo ) ;
}
// Grab individual elements from the combined HTML string. Use each as the default rendering.
// Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
htmlToElements ( html ) . forEach ( function ( el , i ) {
var seg = segs [ i ] ;
if ( el ) {
seg . el = el ;
}
} ) ;
2020-04-01 22:52:43 +00:00
segs = filterSegsViaEls ( this . context , segs , Boolean ( mirrorInfo ) ) ;
2019-08-28 10:59:33 +00:00
}
return segs ;
} ;
// Generic utility for generating the HTML classNames for an event segment's element
FgEventRenderer . prototype . getSegClasses = function ( seg , isDraggable , isResizable , mirrorInfo ) {
var classes = [
'fc-event' ,
seg . isStart ? 'fc-start' : 'fc-not-start' ,
seg . isEnd ? 'fc-end' : 'fc-not-end'
] . concat ( seg . eventRange . ui . classNames ) ;
if ( isDraggable ) {
classes . push ( 'fc-draggable' ) ;
}
if ( isResizable ) {
classes . push ( 'fc-resizable' ) ;
}
if ( mirrorInfo ) {
classes . push ( 'fc-mirror' ) ;
if ( mirrorInfo . isDragging ) {
classes . push ( 'fc-dragging' ) ;
}
if ( mirrorInfo . isResizing ) {
classes . push ( 'fc-resizing' ) ;
}
}
return classes ;
} ;
// Compute the text that should be displayed on an event's element.
// `range` can be the Event object itself, or something range-like, with at least a `start`.
// If event times are disabled, or the event has no time, will return a blank string.
// If not specified, formatter will default to the eventTimeFormat setting,
// and displayEnd will default to the displayEventEnd setting.
FgEventRenderer . prototype . getTimeText = function ( eventRange , formatter , displayEnd ) {
var def = eventRange . def , instance = eventRange . instance ;
return this . _getTimeText ( instance . range . start , def . hasEnd ? instance . range . end : null , def . allDay , formatter , displayEnd , instance . forcedStartTzo , instance . forcedEndTzo ) ;
} ;
FgEventRenderer . prototype . _getTimeText = function ( start , end , allDay , formatter , displayEnd , forcedStartTzo , forcedEndTzo ) {
var dateEnv = this . context . dateEnv ;
if ( formatter == null ) {
formatter = this . eventTimeFormat ;
}
if ( displayEnd == null ) {
displayEnd = this . displayEventEnd ;
}
if ( this . displayEventTime && ! allDay ) {
if ( displayEnd && end ) {
return dateEnv . formatRange ( start , end , formatter , {
forcedStartTzo : forcedStartTzo ,
forcedEndTzo : forcedEndTzo
} ) ;
}
else {
return dateEnv . format ( start , formatter , {
forcedTzo : forcedStartTzo
} ) ;
}
}
return '' ;
} ;
FgEventRenderer . prototype . computeEventTimeFormat = function ( ) {
return {
hour : 'numeric' ,
minute : '2-digit' ,
omitZeroMinute : true
} ;
} ;
FgEventRenderer . prototype . computeDisplayEventTime = function ( ) {
return true ;
} ;
FgEventRenderer . prototype . computeDisplayEventEnd = function ( ) {
return true ;
} ;
// Utility for generating event skin-related CSS properties
FgEventRenderer . prototype . getSkinCss = function ( ui ) {
return {
'background-color' : ui . backgroundColor ,
'border-color' : ui . borderColor ,
color : ui . textColor
} ;
} ;
FgEventRenderer . prototype . sortEventSegs = function ( segs ) {
2020-04-01 22:52:43 +00:00
var specs = this . context . eventOrderSpecs ;
2019-08-28 10:59:33 +00:00
var objs = segs . map ( buildSegCompareObj ) ;
objs . sort ( function ( obj0 , obj1 ) {
return compareByFieldSpecs ( obj0 , obj1 , specs ) ;
} ) ;
return objs . map ( function ( c ) {
return c . _seg ;
} ) ;
} ;
FgEventRenderer . prototype . computeSizes = function ( force ) {
if ( force || this . isSizeDirty ) {
this . computeSegSizes ( this . segs ) ;
}
} ;
FgEventRenderer . prototype . assignSizes = function ( force ) {
if ( force || this . isSizeDirty ) {
this . assignSegSizes ( this . segs ) ;
this . isSizeDirty = false ;
}
} ;
FgEventRenderer . prototype . computeSegSizes = function ( segs ) {
} ;
FgEventRenderer . prototype . assignSegSizes = function ( segs ) {
} ;
// Manipulation on rendered segs
FgEventRenderer . prototype . hideByHash = function ( hash ) {
if ( hash ) {
for ( var _i = 0 , _a = this . segs ; _i < _a . length ; _i ++ ) {
var seg = _a [ _i ] ;
if ( hash [ seg . eventRange . instance . instanceId ] ) {
seg . el . style . visibility = 'hidden' ;
}
}
}
} ;
FgEventRenderer . prototype . showByHash = function ( hash ) {
if ( hash ) {
for ( var _i = 0 , _a = this . segs ; _i < _a . length ; _i ++ ) {
var seg = _a [ _i ] ;
if ( hash [ seg . eventRange . instance . instanceId ] ) {
seg . el . style . visibility = '' ;
}
}
}
} ;
FgEventRenderer . prototype . selectByInstanceId = function ( instanceId ) {
if ( instanceId ) {
for ( var _i = 0 , _a = this . segs ; _i < _a . length ; _i ++ ) {
var seg = _a [ _i ] ;
var eventInstance = seg . eventRange . instance ;
if ( eventInstance && eventInstance . instanceId === instanceId &&
seg . el // necessary?
) {
seg . el . classList . add ( 'fc-selected' ) ;
}
}
}
} ;
FgEventRenderer . prototype . unselectByInstanceId = function ( instanceId ) {
if ( instanceId ) {
for ( var _i = 0 , _a = this . segs ; _i < _a . length ; _i ++ ) {
var seg = _a [ _i ] ;
if ( seg . el ) { // necessary?
seg . el . classList . remove ( 'fc-selected' ) ;
}
}
}
} ;
return FgEventRenderer ;
} ( ) ) ;
// returns a object with all primitive props that can be compared
function buildSegCompareObj ( seg ) {
var eventDef = seg . eventRange . def ;
var range = seg . eventRange . instance . range ;
var start = range . start ? range . start . valueOf ( ) : 0 ; // TODO: better support for open-range events
var end = range . end ? range . end . valueOf ( ) : 0 ; // "
return _ _assign ( { } , eventDef . extendedProps , eventDef , { id : eventDef . publicId , start : start ,
end : end , duration : end - start , allDay : Number ( eventDef . allDay ) , _seg : seg // for later retrieval
} ) ;
}
2020-04-01 22:52:43 +00:00
/ *
TODO : when refactoring this class , make a new FillRenderer instance for each ` type `
* /
2019-08-28 10:59:33 +00:00
var FillRenderer = /** @class */ ( function ( ) {
2020-04-01 22:52:43 +00:00
function FillRenderer ( ) {
2019-08-28 10:59:33 +00:00
this . fillSegTag = 'div' ;
this . dirtySizeFlags = { } ;
this . containerElsByType = { } ;
this . segsByType = { } ;
}
FillRenderer . prototype . getSegsByType = function ( type ) {
return this . segsByType [ type ] || [ ] ;
} ;
2020-04-01 22:52:43 +00:00
FillRenderer . prototype . renderSegs = function ( type , context , segs ) {
2019-08-28 10:59:33 +00:00
var _a ;
2020-04-01 22:52:43 +00:00
this . context = context ;
2019-08-28 10:59:33 +00:00
var renderedSegs = this . renderSegEls ( type , segs ) ; // assignes `.el` to each seg. returns successfully rendered segs
var containerEls = this . attachSegs ( type , renderedSegs ) ;
if ( containerEls ) {
( _a = ( this . containerElsByType [ type ] || ( this . containerElsByType [ type ] = [ ] ) ) ) . push . apply ( _a , containerEls ) ;
}
this . segsByType [ type ] = renderedSegs ;
if ( type === 'bgEvent' ) {
2020-04-01 22:52:43 +00:00
triggerRenderedSegs ( context , renderedSegs , false ) ; // isMirror=false
2019-08-28 10:59:33 +00:00
}
this . dirtySizeFlags [ type ] = true ;
} ;
// Unrenders a specific type of fill that is currently rendered on the grid
2020-04-01 22:52:43 +00:00
FillRenderer . prototype . unrender = function ( type , context ) {
2019-08-28 10:59:33 +00:00
var segs = this . segsByType [ type ] ;
if ( segs ) {
if ( type === 'bgEvent' ) {
2020-04-01 22:52:43 +00:00
triggerWillRemoveSegs ( context , segs , false ) ; // isMirror=false
2019-08-28 10:59:33 +00:00
}
this . detachSegs ( type , segs ) ;
}
} ;
// Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.
// Only returns segments that successfully rendered.
FillRenderer . prototype . renderSegEls = function ( type , segs ) {
var _this = this ;
var html = '' ;
var i ;
if ( segs . length ) {
// build a large concatenation of segment HTML
for ( i = 0 ; i < segs . length ; i ++ ) {
html += this . renderSegHtml ( type , segs [ i ] ) ;
}
// Grab individual elements from the combined HTML string. Use each as the default rendering.
// Then, compute the 'el' for each segment.
htmlToElements ( html ) . forEach ( function ( el , i ) {
var seg = segs [ i ] ;
if ( el ) {
seg . el = el ;
}
} ) ;
if ( type === 'bgEvent' ) {
2020-04-01 22:52:43 +00:00
segs = filterSegsViaEls ( this . context , segs , false // isMirror. background events can never be mirror elements
2019-08-28 10:59:33 +00:00
) ;
}
// correct element type? (would be bad if a non-TD were inserted into a table for example)
segs = segs . filter ( function ( seg ) {
return elementMatches ( seg . el , _this . fillSegTag ) ;
} ) ;
}
return segs ;
} ;
// Builds the HTML needed for one fill segment. Generic enough to work with different types.
FillRenderer . prototype . renderSegHtml = function ( type , seg ) {
var css = null ;
var classNames = [ ] ;
if ( type !== 'highlight' && type !== 'businessHours' ) {
css = {
'background-color' : seg . eventRange . ui . backgroundColor
} ;
}
if ( type !== 'highlight' ) {
classNames = classNames . concat ( seg . eventRange . ui . classNames ) ;
}
if ( type === 'businessHours' ) {
classNames . push ( 'fc-bgevent' ) ;
}
else {
classNames . push ( 'fc-' + type . toLowerCase ( ) ) ;
}
return '<' + this . fillSegTag +
( classNames . length ? ' class="' + classNames . join ( ' ' ) + '"' : '' ) +
( css ? ' style="' + cssToStr ( css ) + '"' : '' ) +
'></' + this . fillSegTag + '>' ;
} ;
FillRenderer . prototype . detachSegs = function ( type , segs ) {
var containerEls = this . containerElsByType [ type ] ;
if ( containerEls ) {
containerEls . forEach ( removeElement ) ;
delete this . containerElsByType [ type ] ;
}
} ;
FillRenderer . prototype . computeSizes = function ( force ) {
for ( var type in this . segsByType ) {
if ( force || this . dirtySizeFlags [ type ] ) {
this . computeSegSizes ( this . segsByType [ type ] ) ;
}
}
} ;
FillRenderer . prototype . assignSizes = function ( force ) {
for ( var type in this . segsByType ) {
if ( force || this . dirtySizeFlags [ type ] ) {
this . assignSegSizes ( this . segsByType [ type ] ) ;
}
}
this . dirtySizeFlags = { } ;
} ;
FillRenderer . prototype . computeSegSizes = function ( segs ) {
} ;
FillRenderer . prototype . assignSegSizes = function ( segs ) {
} ;
return FillRenderer ;
} ( ) ) ;
var NamedTimeZoneImpl = /** @class */ ( function ( ) {
function NamedTimeZoneImpl ( timeZoneName ) {
this . timeZoneName = timeZoneName ;
}
return NamedTimeZoneImpl ;
} ( ) ) ;
/ *
An abstraction for a dragging interaction originating on an event .
Does higher - level things than PointerDragger , such as possibly :
- a "mirror" that moves with the pointer
- a minimum number of pixels or other criteria for a true drag to begin
subclasses must emit :
- pointerdown
- dragstart
- dragmove
- pointerup
- dragend
* /
var ElementDragging = /** @class */ ( function ( ) {
function ElementDragging ( el ) {
this . emitter = new EmitterMixin ( ) ;
}
ElementDragging . prototype . destroy = function ( ) {
} ;
ElementDragging . prototype . setMirrorIsVisible = function ( bool ) {
// optional if subclass doesn't want to support a mirror
} ;
ElementDragging . prototype . setMirrorNeedsRevert = function ( bool ) {
// optional if subclass doesn't want to support a mirror
} ;
ElementDragging . prototype . setAutoScrollEnabled = function ( bool ) {
// optional
} ;
return ElementDragging ;
} ( ) ) ;
function formatDate ( dateInput , settings ) {
if ( settings === void 0 ) { settings = { } ; }
var dateEnv = buildDateEnv$1 ( settings ) ;
var formatter = createFormatter ( settings ) ;
var dateMeta = dateEnv . createMarkerMeta ( dateInput ) ;
if ( ! dateMeta ) { // TODO: warning?
return '' ;
}
return dateEnv . format ( dateMeta . marker , formatter , {
forcedTzo : dateMeta . forcedTzo
} ) ;
}
function formatRange ( startInput , endInput , settings // mixture of env and formatter settings
) {
var dateEnv = buildDateEnv$1 ( typeof settings === 'object' && settings ? settings : { } ) ; // pass in if non-null object
var formatter = createFormatter ( settings , globalDefaults . defaultRangeSeparator ) ;
var startMeta = dateEnv . createMarkerMeta ( startInput ) ;
var endMeta = dateEnv . createMarkerMeta ( endInput ) ;
if ( ! startMeta || ! endMeta ) { // TODO: warning?
return '' ;
}
return dateEnv . formatRange ( startMeta . marker , endMeta . marker , formatter , {
forcedStartTzo : startMeta . forcedTzo ,
forcedEndTzo : endMeta . forcedTzo ,
isEndExclusive : settings . isEndExclusive
} ) ;
}
// TODO: more DRY and optimized
function buildDateEnv$1 ( settings ) {
var locale = buildLocale ( settings . locale || 'en' , parseRawLocales ( [ ] ) . map ) ; // TODO: don't hardcode 'en' everywhere
// ensure required settings
settings = _ _assign ( { timeZone : globalDefaults . timeZone , calendarSystem : 'gregory' } , settings , { locale : locale } ) ;
return new DateEnv ( settings ) ;
}
var DRAG _META _PROPS = {
startTime : createDuration ,
duration : createDuration ,
create : Boolean ,
sourceId : String
} ;
var DRAG _META _DEFAULTS = {
create : true
} ;
function parseDragMeta ( raw ) {
var leftoverProps = { } ;
var refined = refineProps ( raw , DRAG _META _PROPS , DRAG _META _DEFAULTS , leftoverProps ) ;
refined . leftoverProps = leftoverProps ;
return refined ;
}
// Computes a default column header formatting string if `colFormat` is not explicitly defined
function computeFallbackHeaderFormat ( datesRepDistinctDays , dayCnt ) {
// if more than one week row, or if there are a lot of columns with not much space,
// put just the day numbers will be in each cell
if ( ! datesRepDistinctDays || dayCnt > 10 ) {
return { weekday : 'short' } ; // "Sat"
}
else if ( dayCnt > 1 ) {
return { weekday : 'short' , month : 'numeric' , day : 'numeric' , omitCommas : true } ; // "Sat 11/12"
}
else {
return { weekday : 'long' } ; // "Saturday"
}
}
function renderDateCell ( dateMarker , dateProfile , datesRepDistinctDays , colCnt , colHeadFormat , context , colspan , otherAttrs ) {
2020-04-01 22:52:43 +00:00
var dateEnv = context . dateEnv , theme = context . theme , options = context . options ;
2019-08-28 10:59:33 +00:00
var isDateValid = rangeContainsMarker ( dateProfile . activeRange , dateMarker ) ; // TODO: called too frequently. cache somehow.
var classNames = [
'fc-day-header' ,
theme . getClass ( 'widgetHeader' )
] ;
var innerHtml ;
if ( typeof options . columnHeaderHtml === 'function' ) {
innerHtml = options . columnHeaderHtml ( dateEnv . toDate ( dateMarker ) ) ;
}
else if ( typeof options . columnHeaderText === 'function' ) {
innerHtml = htmlEscape ( options . columnHeaderText ( dateEnv . toDate ( dateMarker ) ) ) ;
}
else {
innerHtml = htmlEscape ( dateEnv . format ( dateMarker , colHeadFormat ) ) ;
}
// if only one row of days, the classNames on the header can represent the specific days beneath
if ( datesRepDistinctDays ) {
classNames = classNames . concat (
// includes the day-of-week class
// noThemeHighlight=true (don't highlight the header)
getDayClasses ( dateMarker , dateProfile , context , true ) ) ;
}
else {
classNames . push ( 'fc-' + DAY _IDS [ dateMarker . getUTCDay ( ) ] ) ; // only add the day-of-week class
}
return '' +
'<th class="' + classNames . join ( ' ' ) + '"' +
( ( isDateValid && datesRepDistinctDays ) ?
' data-date="' + dateEnv . formatIso ( dateMarker , { omitTime : true } ) + '"' :
'' ) +
( colspan > 1 ?
' colspan="' + colspan + '"' :
'' ) +
( otherAttrs ?
' ' + otherAttrs :
'' ) +
'>' +
( isDateValid ?
// don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
2020-04-01 22:52:43 +00:00
buildGotoAnchorHtml ( options , dateEnv , { date : dateMarker , forceOff : ! datesRepDistinctDays || colCnt === 1 } , innerHtml ) :
2019-08-28 10:59:33 +00:00
// if not valid, display text, but no link
innerHtml ) +
'</th>' ;
}
var DayHeader = /** @class */ ( function ( _super ) {
_ _extends ( DayHeader , _super ) ;
2020-04-01 22:52:43 +00:00
function DayHeader ( parentEl ) {
var _this = _super . call ( this ) || this ;
_this . renderSkeleton = memoizeRendering ( _this . _renderSkeleton , _this . _unrenderSkeleton ) ;
_this . parentEl = parentEl ;
2019-08-28 10:59:33 +00:00
return _this ;
}
2020-04-01 22:52:43 +00:00
DayHeader . prototype . render = function ( props , context ) {
2019-08-28 10:59:33 +00:00
var dates = props . dates , datesRepDistinctDays = props . datesRepDistinctDays ;
var parts = [ ] ;
2020-04-01 22:52:43 +00:00
this . renderSkeleton ( context ) ;
2019-08-28 10:59:33 +00:00
if ( props . renderIntroHtml ) {
parts . push ( props . renderIntroHtml ( ) ) ;
}
2020-04-01 22:52:43 +00:00
var colHeadFormat = createFormatter ( context . options . columnHeaderFormat ||
2019-08-28 10:59:33 +00:00
computeFallbackHeaderFormat ( datesRepDistinctDays , dates . length ) ) ;
for ( var _i = 0 , dates _1 = dates ; _i < dates _1 . length ; _i ++ ) {
var date = dates _1 [ _i ] ;
2020-04-01 22:52:43 +00:00
parts . push ( renderDateCell ( date , props . dateProfile , datesRepDistinctDays , dates . length , colHeadFormat , context ) ) ;
2019-08-28 10:59:33 +00:00
}
2020-04-01 22:52:43 +00:00
if ( context . isRtl ) {
2019-08-28 10:59:33 +00:00
parts . reverse ( ) ;
}
this . thead . innerHTML = '<tr>' + parts . join ( '' ) + '</tr>' ;
} ;
2020-04-01 22:52:43 +00:00
DayHeader . prototype . destroy = function ( ) {
_super . prototype . destroy . call ( this ) ;
this . renderSkeleton . unrender ( ) ;
} ;
DayHeader . prototype . _renderSkeleton = function ( context ) {
var theme = context . theme ;
var parentEl = this . parentEl ;
parentEl . innerHTML = '' ; // because might be nbsp
parentEl . appendChild ( this . el = htmlToElement ( '<div class="fc-row ' + theme . getClass ( 'headerRow' ) + '">' +
'<table class="' + theme . getClass ( 'tableGrid' ) + '">' +
'<thead></thead>' +
'</table>' +
'</div>' ) ) ;
this . thead = this . el . querySelector ( 'thead' ) ;
} ;
DayHeader . prototype . _unrenderSkeleton = function ( ) {
removeElement ( this . el ) ;
} ;
2019-08-28 10:59:33 +00:00
return DayHeader ;
} ( Component ) ) ;
var DaySeries = /** @class */ ( function ( ) {
function DaySeries ( range , dateProfileGenerator ) {
var date = range . start ;
var end = range . end ;
var indices = [ ] ;
var dates = [ ] ;
var dayIndex = - 1 ;
while ( date < end ) { // loop each day from start to end
if ( dateProfileGenerator . isHiddenDay ( date ) ) {
indices . push ( dayIndex + 0.5 ) ; // mark that it's between indices
}
else {
dayIndex ++ ;
indices . push ( dayIndex ) ;
dates . push ( date ) ;
}
date = addDays ( date , 1 ) ;
}
this . dates = dates ;
this . indices = indices ;
this . cnt = dates . length ;
}
DaySeries . prototype . sliceRange = function ( range ) {
var firstIndex = this . getDateDayIndex ( range . start ) ; // inclusive first index
var lastIndex = this . getDateDayIndex ( addDays ( range . end , - 1 ) ) ; // inclusive last index
var clippedFirstIndex = Math . max ( 0 , firstIndex ) ;
var clippedLastIndex = Math . min ( this . cnt - 1 , lastIndex ) ;
// deal with in-between indices
clippedFirstIndex = Math . ceil ( clippedFirstIndex ) ; // in-between starts round to next cell
clippedLastIndex = Math . floor ( clippedLastIndex ) ; // in-between ends round to prev cell
if ( clippedFirstIndex <= clippedLastIndex ) {
return {
firstIndex : clippedFirstIndex ,
lastIndex : clippedLastIndex ,
isStart : firstIndex === clippedFirstIndex ,
isEnd : lastIndex === clippedLastIndex
} ;
}
else {
return null ;
}
} ;
// Given a date, returns its chronolocial cell-index from the first cell of the grid.
// If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
// If before the first offset, returns a negative number.
// If after the last offset, returns an offset past the last cell offset.
// Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
DaySeries . prototype . getDateDayIndex = function ( date ) {
var indices = this . indices ;
var dayOffset = Math . floor ( diffDays ( this . dates [ 0 ] , date ) ) ;
if ( dayOffset < 0 ) {
return indices [ 0 ] - 1 ;
}
else if ( dayOffset >= indices . length ) {
return indices [ indices . length - 1 ] + 1 ;
}
else {
return indices [ dayOffset ] ;
}
} ;
return DaySeries ;
} ( ) ) ;
var DayTable = /** @class */ ( function ( ) {
function DayTable ( daySeries , breakOnWeeks ) {
var dates = daySeries . dates ;
var daysPerRow ;
var firstDay ;
var rowCnt ;
if ( breakOnWeeks ) {
// count columns until the day-of-week repeats
firstDay = dates [ 0 ] . getUTCDay ( ) ;
for ( daysPerRow = 1 ; daysPerRow < dates . length ; daysPerRow ++ ) {
if ( dates [ daysPerRow ] . getUTCDay ( ) === firstDay ) {
break ;
}
}
rowCnt = Math . ceil ( dates . length / daysPerRow ) ;
}
else {
rowCnt = 1 ;
daysPerRow = dates . length ;
}
this . rowCnt = rowCnt ;
this . colCnt = daysPerRow ;
this . daySeries = daySeries ;
this . cells = this . buildCells ( ) ;
this . headerDates = this . buildHeaderDates ( ) ;
}
DayTable . prototype . buildCells = function ( ) {
var rows = [ ] ;
for ( var row = 0 ; row < this . rowCnt ; row ++ ) {
var cells = [ ] ;
for ( var col = 0 ; col < this . colCnt ; col ++ ) {
cells . push ( this . buildCell ( row , col ) ) ;
}
rows . push ( cells ) ;
}
return rows ;
} ;
DayTable . prototype . buildCell = function ( row , col ) {
return {
date : this . daySeries . dates [ row * this . colCnt + col ]
} ;
} ;
DayTable . prototype . buildHeaderDates = function ( ) {
var dates = [ ] ;
for ( var col = 0 ; col < this . colCnt ; col ++ ) {
dates . push ( this . cells [ 0 ] [ col ] . date ) ;
}
return dates ;
} ;
DayTable . prototype . sliceRange = function ( range ) {
var colCnt = this . colCnt ;
var seriesSeg = this . daySeries . sliceRange ( range ) ;
var segs = [ ] ;
if ( seriesSeg ) {
var firstIndex = seriesSeg . firstIndex , lastIndex = seriesSeg . lastIndex ;
var index = firstIndex ;
while ( index <= lastIndex ) {
var row = Math . floor ( index / colCnt ) ;
var nextIndex = Math . min ( ( row + 1 ) * colCnt , lastIndex + 1 ) ;
segs . push ( {
row : row ,
firstCol : index % colCnt ,
lastCol : ( nextIndex - 1 ) % colCnt ,
isStart : seriesSeg . isStart && index === firstIndex ,
isEnd : seriesSeg . isEnd && ( nextIndex - 1 ) === lastIndex
} ) ;
index = nextIndex ;
}
}
return segs ;
} ;
return DayTable ;
} ( ) ) ;
var Slicer = /** @class */ ( function ( ) {
function Slicer ( ) {
this . sliceBusinessHours = memoize ( this . _sliceBusinessHours ) ;
this . sliceDateSelection = memoize ( this . _sliceDateSpan ) ;
this . sliceEventStore = memoize ( this . _sliceEventStore ) ;
this . sliceEventDrag = memoize ( this . _sliceInteraction ) ;
this . sliceEventResize = memoize ( this . _sliceInteraction ) ;
}
2020-04-01 22:52:43 +00:00
Slicer . prototype . sliceProps = function ( props , dateProfile , nextDayThreshold , calendar , component ) {
2019-08-28 10:59:33 +00:00
var extraArgs = [ ] ;
2020-04-01 22:52:43 +00:00
for ( var _i = 5 ; _i < arguments . length ; _i ++ ) {
extraArgs [ _i - 5 ] = arguments [ _i ] ;
2019-08-28 10:59:33 +00:00
}
var eventUiBases = props . eventUiBases ;
var eventSegs = this . sliceEventStore . apply ( this , [ props . eventStore , eventUiBases , dateProfile , nextDayThreshold , component ] . concat ( extraArgs ) ) ;
return {
dateSelectionSegs : this . sliceDateSelection . apply ( this , [ props . dateSelection , eventUiBases , component ] . concat ( extraArgs ) ) ,
2020-04-01 22:52:43 +00:00
businessHourSegs : this . sliceBusinessHours . apply ( this , [ props . businessHours , dateProfile , nextDayThreshold , calendar , component ] . concat ( extraArgs ) ) ,
2019-08-28 10:59:33 +00:00
fgEventSegs : eventSegs . fg ,
bgEventSegs : eventSegs . bg ,
eventDrag : this . sliceEventDrag . apply ( this , [ props . eventDrag , eventUiBases , dateProfile , nextDayThreshold , component ] . concat ( extraArgs ) ) ,
eventResize : this . sliceEventResize . apply ( this , [ props . eventResize , eventUiBases , dateProfile , nextDayThreshold , component ] . concat ( extraArgs ) ) ,
eventSelection : props . eventSelection
} ; // TODO: give interactionSegs?
} ;
Slicer . prototype . sliceNowDate = function ( // does not memoize
date , component ) {
var extraArgs = [ ] ;
for ( var _i = 2 ; _i < arguments . length ; _i ++ ) {
extraArgs [ _i - 2 ] = arguments [ _i ] ;
}
return this . _sliceDateSpan . apply ( this , [ { range : { start : date , end : addMs ( date , 1 ) } , allDay : false } ,
{ } ,
component ] . concat ( extraArgs ) ) ;
} ;
2020-04-01 22:52:43 +00:00
Slicer . prototype . _sliceBusinessHours = function ( businessHours , dateProfile , nextDayThreshold , calendar , component ) {
2019-08-28 10:59:33 +00:00
var extraArgs = [ ] ;
2020-04-01 22:52:43 +00:00
for ( var _i = 5 ; _i < arguments . length ; _i ++ ) {
extraArgs [ _i - 5 ] = arguments [ _i ] ;
2019-08-28 10:59:33 +00:00
}
if ( ! businessHours ) {
return [ ] ;
}
2020-04-01 22:52:43 +00:00
return this . _sliceEventStore . apply ( this , [ expandRecurring ( businessHours , computeActiveRange ( dateProfile , Boolean ( nextDayThreshold ) ) , calendar ) ,
2019-08-28 10:59:33 +00:00
{ } ,
dateProfile ,
nextDayThreshold ,
component ] . concat ( extraArgs ) ) . bg ;
} ;
Slicer . prototype . _sliceEventStore = function ( eventStore , eventUiBases , dateProfile , nextDayThreshold , component ) {
var extraArgs = [ ] ;
for ( var _i = 5 ; _i < arguments . length ; _i ++ ) {
extraArgs [ _i - 5 ] = arguments [ _i ] ;
}
if ( eventStore ) {
var rangeRes = sliceEventStore ( eventStore , eventUiBases , computeActiveRange ( dateProfile , Boolean ( nextDayThreshold ) ) , nextDayThreshold ) ;
return {
bg : this . sliceEventRanges ( rangeRes . bg , component , extraArgs ) ,
fg : this . sliceEventRanges ( rangeRes . fg , component , extraArgs )
} ;
}
else {
return { bg : [ ] , fg : [ ] } ;
}
} ;
Slicer . prototype . _sliceInteraction = function ( interaction , eventUiBases , dateProfile , nextDayThreshold , component ) {
var extraArgs = [ ] ;
for ( var _i = 5 ; _i < arguments . length ; _i ++ ) {
extraArgs [ _i - 5 ] = arguments [ _i ] ;
}
if ( ! interaction ) {
return null ;
}
var rangeRes = sliceEventStore ( interaction . mutatedEvents , eventUiBases , computeActiveRange ( dateProfile , Boolean ( nextDayThreshold ) ) , nextDayThreshold ) ;
return {
segs : this . sliceEventRanges ( rangeRes . fg , component , extraArgs ) ,
affectedInstances : interaction . affectedEvents . instances ,
isEvent : interaction . isEvent ,
sourceSeg : interaction . origSeg
} ;
} ;
Slicer . prototype . _sliceDateSpan = function ( dateSpan , eventUiBases , component ) {
var extraArgs = [ ] ;
for ( var _i = 3 ; _i < arguments . length ; _i ++ ) {
extraArgs [ _i - 3 ] = arguments [ _i ] ;
}
if ( ! dateSpan ) {
return [ ] ;
}
2020-04-01 22:52:43 +00:00
var eventRange = fabricateEventRange ( dateSpan , eventUiBases , component . context . calendar ) ;
2019-08-28 10:59:33 +00:00
var segs = this . sliceRange . apply ( this , [ dateSpan . range ] . concat ( extraArgs ) ) ;
for ( var _a = 0 , segs _1 = segs ; _a < segs _1 . length ; _a ++ ) {
var seg = segs _1 [ _a ] ;
seg . component = component ;
seg . eventRange = eventRange ;
}
return segs ;
} ;
/ *
"complete" seg means it has component and eventRange
* /
Slicer . prototype . sliceEventRanges = function ( eventRanges , component , // TODO: kill
extraArgs ) {
var segs = [ ] ;
for ( var _i = 0 , eventRanges _1 = eventRanges ; _i < eventRanges _1 . length ; _i ++ ) {
var eventRange = eventRanges _1 [ _i ] ;
segs . push . apply ( segs , this . sliceEventRange ( eventRange , component , extraArgs ) ) ;
}
return segs ;
} ;
/ *
"complete" seg means it has component and eventRange
* /
Slicer . prototype . sliceEventRange = function ( eventRange , component , // TODO: kill
extraArgs ) {
var segs = this . sliceRange . apply ( this , [ eventRange . range ] . concat ( extraArgs ) ) ;
for ( var _i = 0 , segs _2 = segs ; _i < segs _2 . length ; _i ++ ) {
var seg = segs _2 [ _i ] ;
seg . component = component ;
seg . eventRange = eventRange ;
seg . isStart = eventRange . isStart && seg . isStart ;
seg . isEnd = eventRange . isEnd && seg . isEnd ;
}
return segs ;
} ;
return Slicer ;
} ( ) ) ;
/ *
for incorporating minTime / maxTime if appropriate
TODO : should be part of DateProfile !
TimelineDateProfile already does this btw
* /
function computeActiveRange ( dateProfile , isComponentAllDay ) {
var range = dateProfile . activeRange ;
if ( isComponentAllDay ) {
return range ;
}
return {
start : addMs ( range . start , dateProfile . minTime . milliseconds ) ,
end : addMs ( range . end , dateProfile . maxTime . milliseconds - 864e5 ) // 864e5 = ms in a day
} ;
}
// exports
// --------------------------------------------------------------------------------------------------
2020-06-01 11:05:25 +00:00
var version = '4.4.2' ;
2019-08-28 10:59:33 +00:00
2020-04-01 22:52:43 +00:00
export { Calendar , Component , ComponentContext , DateComponent , DateEnv , DateProfileGenerator , DayHeader , DaySeries , DayTable , ElementDragging , ElementScrollController , EmitterMixin , EventApi , FgEventRenderer , FillRenderer , Interaction , Mixin , NamedTimeZoneImpl , PositionCache , ScrollComponent , ScrollController , Slicer , Splitter , Theme , View , WindowScrollController , addDays , addDurations , addMs , addWeeks , allowContextMenu , allowSelection , appendToElement , applyAll , applyMutationToEventStore , applyStyle , applyStyleProp , asRoughMinutes , asRoughMs , asRoughSeconds , buildGotoAnchorHtml , buildSegCompareObj , capitaliseFirstLetter , combineEventUis , compareByFieldSpec , compareByFieldSpecs , compareNumbers , compensateScroll , computeClippingRect , computeEdges , computeEventDraggable , computeEventEndResizable , computeEventStartResizable , computeFallbackHeaderFormat , computeHeightAndMargins , computeInnerRect , computeRect , computeVisibleDayRange , config , constrainPoint , createDuration , createElement , createEmptyEventStore , createEventInstance , createFormatter , createPlugin , cssToStr , debounce , diffDates , diffDayAndTime , diffDays , diffPoints , diffWeeks , diffWholeDays , diffWholeWeeks , disableCursor , distributeHeight , elementClosest , elementMatches , enableCursor , eventTupleToStore , filterEventStoreDefs , filterHash , findChildren , findElements , flexibleCompare , forceClassName , formatDate , formatIsoTimeString , formatRange , getAllDayHtml , getClippingParents , getDayClasses , getElSeg , getRectCenter , getRelevantEvents , globalDefaults , greatestDurationDenominator , hasBgRendering , htmlEscape , htmlToElement , insertAfterElement , interactionSettingsStore , interactionSettingsToStore , intersectRanges , intersectRects , isArraysEqual , isDateSpansEqual , isInt , isInteractionValid , isMultiDayRange , isPropsEqual , isPropsValid , isSingleDay , isValidDate , listenBySelector , mapHash , matchCellWidths , memoize , memoizeOutput , memoizeRendering , mergeEventStores , multiplyDuration , padStart , parseBusinessHours , parseDragMeta , parseEventDef , parseFieldSpecs , parse as parseMarker , pointInsideRect , prependToElement , preventContextMenu , preventDefault , preventSelection , processScopedUiProps , rangeContainsMarker , rangeContainsRange , rangesEqual , rangesIntersect , refineProps , removeElement , removeExact , renderDateCell , requestJson , sliceEventStore , startOfDay , subtractInnerElHeight , translateRect , uncompensateScroll , undistributeHeight , unpromisify , version , whenTransitionDone , wholeDivideDurations } ;