Skip to content
Snippets Groups Projects
main.js 918 KiB
Newer Older
  • Learn to ignore specific revisions
  •             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)
            // slotMinTime or slotMaxTime causes the range to expand.
            DateProfileGenerator.prototype.adjustActiveRange = function (range) {
                var _a = this.props, dateEnv = _a.dateEnv, usesMinMaxTime = _a.usesMinMaxTime, slotMinTime = _a.slotMinTime, slotMaxTime = _a.slotMaxTime;
    
                var start = range.start, end = range.end;
    
                if (usesMinMaxTime) {
                    // expand active range if slotMinTime is negative (why not when positive?)
                    if (asRoughDays(slotMinTime) < 0) {
                        start = startOfDay(start); // necessary?
                        start = dateEnv.add(start, slotMinTime);
                    }
                    // expand active range if slotMaxTime is beyond one day (why not when negative?)
                    if (asRoughDays(slotMaxTime) > 1) {
                        end = startOfDay(end); // necessary?
                        end = addDays(end, -1);
                        end = dateEnv.add(end, slotMaxTime);
                    }
                }
                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 _a = this.props, dateEnv = _a.dateEnv, dateAlignment = _a.dateAlignment;
                var start;
                var end;
                var res;
                // compute what the alignment should be
                if (!dateAlignment) {
                    var dateIncrement = this.props.dateIncrement;
                    if (dateIncrement) {
                        // use the smaller of the two units
                        if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
                            dateAlignment = greatestDurationDenominator(dateIncrement).unit;
                        }
                        else {
                            dateAlignment = unit;
                        }
                    }
                    else {
                        dateAlignment = 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, dateAlignment);
                    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 _a = this.props, dateEnv = _a.dateEnv, dateAlignment = _a.dateAlignment;
                var runningCount = 0;
                var start = date;
                var end;
                if (dateAlignment) {
                    start = dateEnv.startOf(start, dateAlignment);
                }
                start = startOfDay(start);
                start = this.skipHiddenDays(start, direction);
                end = start;
                do {
                    end = addDays(end, 1);
                    if (!this.isHiddenDay(end)) {
    
                        runningCount += 1;
    
                    }
                } 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 props = this.props;
                var input = props.visibleRangeInput;
                var simpleInput = typeof input === 'function'
                    ? input.call(props.calendarApi, props.dateEnv.toDate(date))
                    : input;
                var range = this.refineRange(simpleInput);
                if (range && (range.start == null || range.end == null)) {
                    return null;
                }
                return range;
            };
            // 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 dateIncrement = this.props.dateIncrement;
                var customAlignment;
                if (dateIncrement) {
                    return dateIncrement;
                }
    
                if ((customAlignment = this.props.dateAlignment)) {
    
                    return createDuration(1, customAlignment);
                }
    
                if (fallback) {
    
                return createDuration({ days: 1 });
    
            };
            DateProfileGenerator.prototype.refineRange = function (rangeInput) {
                if (rangeInput) {
                    var range = parseRange(rangeInput, this.props.dateEnv);
                    if (range) {
                        range = computeVisibleDayRange(range);
                    }
                    return range;
                }
                return null;
            };
            /* Hidden Days
            ------------------------------------------------------------------------------------------------------------------*/
            // Initializes internal variables related to calculating hidden days-of-week
            DateProfileGenerator.prototype.initHiddenDays = function () {
                var hiddenDays = this.props.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.props.weekends === false) {
                    hiddenDays.push(0, 6); // 0=sunday, 6=saturday
                }
    
                for (i = 0; i < 7; i += 1) {
    
                    if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
    
                        dayCnt += 1;
    
                    }
                }
                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, 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;
        }());
    
        function reduceViewType(viewType, action) {
            switch (action.type) {
                case 'CHANGE_VIEW_TYPE':
    
                    viewType = action.viewType;
    
            }
            return viewType;
        }
    
        function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
            var _a;
            switch (action.type) {
                case 'SET_OPTION':
                    return __assign(__assign({}, dynamicOptionOverrides), (_a = {}, _a[action.optionName] = action.rawOptionValue, _a));
                default:
                    return dynamicOptionOverrides;
            }
        }
    
        function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
            var dp;
            switch (action.type) {
                case 'CHANGE_VIEW_TYPE':
                    return dateProfileGenerator.build(action.dateMarker || currentDate);
                case 'CHANGE_DATE':
                    if (!currentDateProfile.activeRange ||
                        !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker) // don't move if date already in view
                    ) {
                        return dateProfileGenerator.build(action.dateMarker);
                    }
                    break;
                case 'PREV':
                    dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
                    if (dp.isValid) {
                        return dp;
                    }
                    break;
                case 'NEXT':
                    dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
                    if (dp.isValid) {
                        return dp;
                    }
                    break;
            }
            return currentDateProfile;
        }
    
        function initEventSources(calendarOptions, dateProfile, context) {
            var activeRange = dateProfile ? dateProfile.activeRange : null;
            return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
        }
        function reduceEventSources(eventSources, action, dateProfile, context) {
            var activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
            switch (action.type) {
                case 'ADD_EVENT_SOURCES': // already parsed
                    return addSources(eventSources, action.sources, activeRange, context);
                case 'REMOVE_EVENT_SOURCE':
                    return removeSource(eventSources, action.sourceId);
                case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
                case 'NEXT':
                case 'CHANGE_DATE':
                case 'CHANGE_VIEW_TYPE':
                    if (dateProfile) {
                        return fetchDirtySources(eventSources, activeRange, context);
                    }
    
                    return eventSources;
    
                case 'FETCH_EVENT_SOURCES':
                    return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
                        arrayToHash(action.sourceIds) :
                        excludeStaticSources(eventSources, context), activeRange, context);
                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;
            }
        }
        function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
            var activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
            return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, context);
        }
    
        function computeEventSourcesLoading(eventSources) {
    
            for (var sourceId in eventSources) {
                if (eventSources[sourceId].isFetching) {
    
                    return true;
    
            return false;
    
        }
        function addSources(eventSourceHash, sources, fetchRange, context) {
            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, context);
            }
            return __assign(__assign({}, eventSourceHash), hash);
        }
        function removeSource(eventSourceHash, sourceId) {
    
            return filterHash(eventSourceHash, function (eventSource) { return eventSource.sourceId !== sourceId; });
    
        }
        function fetchDirtySources(sourceHash, fetchRange, context) {
    
            return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { return isSourceDirty(eventSource, fetchRange, context); }), fetchRange, context);
    
        }
        function isSourceDirty(eventSource, fetchRange, context) {
            if (!doesSourceNeedRange(eventSource, context)) {
                return !eventSource.latestFetchId;
            }
    
            return !context.options.lazyFetching ||
                !eventSource.fetchRange ||
                eventSource.isFetching || // always cancel outdated in-progress fetches
                fetchRange.start < eventSource.fetchRange.start ||
                fetchRange.end > eventSource.fetchRange.end;
    
        }
        function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, context) {
            var nextSources = {};
            for (var sourceId in prevSources) {
                var source = prevSources[sourceId];
                if (sourceIdHash[sourceId]) {
                    nextSources[sourceId] = fetchSource(source, fetchRange, context);
                }
                else {
                    nextSources[sourceId] = source;
                }
            }
            return nextSources;
        }
        function fetchSource(eventSource, fetchRange, context) {
            var options = context.options, calendarApi = context.calendarApi;
            var sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
            var fetchId = guid();
            sourceDef.fetch({
                eventSource: eventSource,
                range: fetchRange,
    
                context: context,
    
            }, function (res) {
                var rawEvents = res.rawEvents;
                if (options.eventSourceSuccess) {
                    rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.xhr) || rawEvents;
                }
                if (eventSource.success) {
                    rawEvents = eventSource.success.call(calendarApi, rawEvents, res.xhr) || rawEvents;
                }
                context.dispatch({
                    type: 'RECEIVE_EVENTS',
                    sourceId: eventSource.sourceId,
                    fetchId: fetchId,
                    fetchRange: fetchRange,
    
                    rawEvents: rawEvents,
    
                });
            }, function (error) {
                console.warn(error.message, error);
                if (options.eventSourceFailure) {
                    options.eventSourceFailure.call(calendarApi, error);
                }
                if (eventSource.failure) {
                    eventSource.failure(error);
                }
                context.dispatch({
                    type: 'RECEIVE_EVENT_ERROR',
                    sourceId: eventSource.sourceId,
                    fetchId: fetchId,
                    fetchRange: fetchRange,
    
                    error: error,
    
                });
            });
            return __assign(__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) {
    
                return __assign(__assign({}, sourceHash), (_a = {}, _a[sourceId] = __assign(__assign({}, eventSource), { isFetching: false, fetchRange: fetchRange }), _a));
    
            }
            return sourceHash;
        }
        function excludeStaticSources(eventSources, context) {
    
            return filterHash(eventSources, function (eventSource) { return doesSourceNeedRange(eventSource, context); });
    
        }
        function parseInitialSources(rawOptions, context) {
            var refiners = buildEventSourceRefiners(context);
            var rawSources = [].concat(rawOptions.eventSources || []);
            var sources = []; // parsed
            if (rawOptions.initialEvents) {
                rawSources.unshift(rawOptions.initialEvents);
            }
            if (rawOptions.events) {
                rawSources.unshift(rawOptions.events);
            }
            for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) {
                var rawSource = rawSources_1[_i];
                var source = parseEventSource(rawSource, context, refiners);
                if (source) {
                    sources.push(source);
                }
            }
            return sources;
        }
        function doesSourceNeedRange(eventSource, context) {
            var defs = context.pluginHooks.eventSourceDefs;
            return !defs[eventSource.sourceDefId].ignoreRange;
        }
    
        function reduceDateSelection(currentSelection, action) {
            switch (action.type) {
                case 'UNSELECT_DATES':
                    return null;
                case 'SELECT_DATES':
                    return action.selection;
                default:
                    return currentSelection;
            }
        }
    
        function reduceSelectedEvent(currentInstanceId, action) {
            switch (action.type) {
                case 'UNSELECT_EVENT':
                    return '';
                case 'SELECT_EVENT':
                    return action.eventInstanceId;
                default:
                    return currentInstanceId;
            }
        }
    
        function reduceEventDrag(currentDrag, action) {
            var newDrag;
            switch (action.type) {
                case 'UNSET_EVENT_DRAG':
                    return null;
                case 'SET_EVENT_DRAG':
                    newDrag = action.state;
                    return {
                        affectedEvents: newDrag.affectedEvents,
                        mutatedEvents: newDrag.mutatedEvents,
    
                        isEvent: newDrag.isEvent,
    
                    };
                default:
                    return currentDrag;
            }
        }
    
        function reduceEventResize(currentResize, action) {
            var newResize;
            switch (action.type) {
                case 'UNSET_EVENT_RESIZE':
                    return null;
                case 'SET_EVENT_RESIZE':
                    newResize = action.state;
                    return {
                        affectedEvents: newResize.affectedEvents,
                        mutatedEvents: newResize.mutatedEvents,
    
                        isEvent: newResize.isEvent,
    
                    };
                default:
                    return currentResize;
            }
        }
    
        function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
            var viewsWithButtons = [];
            var headerToolbar = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) : null;
            var footerToolbar = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) : null;
            return { headerToolbar: headerToolbar, footerToolbar: footerToolbar, viewsWithButtons: viewsWithButtons };
        }
    
        function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) {
    
            return mapHash(sectionStrHash, function (sectionStr) { return parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons); });
        }
        /*
        BAD: querying icons and text here. should be done at render time
        */
    
        function parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi, viewsWithButtons) {
    
            var isRtl = calendarOptions.direction === 'rtl';
            var calendarCustomButtons = calendarOptions.customButtons || {};
            var calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
            var calendarButtonText = calendarOptions.buttonText || {};
            var sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
    
            return sectionSubstrs.map(function (buttonGroupStr) { return (buttonGroupStr.split(',').map(function (buttonName) {
                if (buttonName === 'title') {
                    return { buttonName: buttonName };
                }
                var customButtonProps;
                var viewSpec;
                var buttonClick;
                var buttonIcon; // only one of these will be set
                var buttonText; // "
                if ((customButtonProps = calendarCustomButtons[buttonName])) {
                    buttonClick = function (ev) {
                        if (customButtonProps.click) {
                            customButtonProps.click.call(ev.target, ev, ev.target);
    
                    };
                    (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
                        (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
                        (buttonText = customButtonProps.text);
                }
                else if ((viewSpec = viewSpecs[buttonName])) {
                    viewsWithButtons.push(buttonName);
                    buttonClick = function () {
                        calendarApi.changeView(buttonName);
                    };
                    (buttonText = viewSpec.buttonTextOverride) ||
                        (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
                        (buttonText = viewSpec.buttonTextDefault);
                }
                else if (calendarApi[buttonName]) { // a calendarApi method
                    buttonClick = function () {
                        calendarApi[buttonName]();
                    };
                    (buttonText = calendarButtonTextOverrides[buttonName]) ||
                        (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
                        (buttonText = calendarButtonText[buttonName]);
                    //            ^ everything else is considered default
                }
                return { buttonName: buttonName, buttonClick: buttonClick, buttonIcon: buttonIcon, buttonText: buttonText };
            })); });
    
        }
    
        var eventSourceDef = {
            ignoreRange: true,
            parseMeta: function (refined) {
                if (Array.isArray(refined.events)) {
                    return refined.events;
                }
                return null;
            },
            fetch: function (arg, success) {
                success({
    
                    rawEvents: arg.eventSource.meta,
    
        };
        var arrayEventSourcePlugin = createPlugin({
    
            eventSourceDefs: [eventSourceDef],
    
        });
    
        var eventSourceDef$1 = {
            parseMeta: function (refined) {
                if (typeof refined.events === 'function') {
                    return refined.events;
                }
                return null;
            },
            fetch: function (arg, success, failure) {
                var dateEnv = arg.context.dateEnv;
                var func = arg.eventSource.meta;
                unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), function (rawEvents) {
                    success({ rawEvents: rawEvents }); // needs an object response
    
                }, failure);
            },
    
        };
        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) {
                    var parsed = false;
                    var res = void 0;
                    try {
                        res = JSON.parse(xhr.responseText);
                        parsed = true;
                    }
                    catch (err) {
                        // will handle parsed=false
                    }
                    if (parsed) {
                        successCallback(res, xhr);
                    }
                    else {
                        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 JSON_FEED_EVENT_SOURCE_REFINERS = {
            method: String,
            extraParams: identity,
            startParam: String,
            endParam: String,
    
            timeZoneParam: String,
    
        };
    
        var eventSourceDef$2 = {
            parseMeta: function (refined) {
    
                if (refined.url && (refined.format === 'json' || !refined.format)) {
    
                    return {
                        url: refined.url,
    
                        format: 'json',
    
                        method: (refined.method || 'GET').toUpperCase(),
                        extraParams: refined.extraParams,
                        startParam: refined.startParam,
                        endParam: refined.endParam,
    
                        timeZoneParam: refined.timeZoneParam,
    
                    };
                }
                return null;
            },
            fetch: function (arg, success, failure) {
                var meta = arg.eventSource.meta;
                var requestParams = buildRequestParams(meta, arg.range, arg.context);
                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({
            eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
    
            eventSourceDefs: [eventSourceDef$2],
    
        });
        function buildRequestParams(meta, range, context) {
            var dateEnv = context.dateEnv, options = context.options;
            var startParam;
            var endParam;
            var timeZoneParam;
            var customRequestParams;
            var params = {};
            startParam = meta.startParam;
            if (startParam == null) {
                startParam = options.startParam;
            }
            endParam = meta.endParam;
            if (endParam == null) {
                endParam = options.endParam;
            }
            timeZoneParam = meta.timeZoneParam;
            if (timeZoneParam == null) {
                timeZoneParam = options.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 SIMPLE_RECURRING_REFINERS = {
            daysOfWeek: identity,
            startTime: createDuration,
            endTime: createDuration,
            duration: createDuration,
            startRecur: identity,
    
            endRecur: identity,
    
        };
    
        var recurring = {
            parse: function (refined, dateEnv) {
                if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
                    var recurringData = {
                        daysOfWeek: refined.daysOfWeek || null,
                        startTime: refined.startTime || null,
                        endTime: refined.endTime || null,
                        startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
    
                        endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
    
                    };
                    var duration = void 0;
                    if (refined.duration) {
                        duration = refined.duration;
                    }
                    if (!duration && refined.startTime && refined.endTime) {
                        duration = subtractDurations(refined.endTime, refined.startTime);
                    }
                    return {
                        allDayGuess: Boolean(!refined.startTime && !refined.endTime),
                        duration: duration,
    
                        typeData: recurringData,
    
                    };
                }
                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);
                }
    
        };
        var simpleRecurringEventsPlugin = createPlugin({
            recurringTypes: [recurring],
    
            eventRefiners: SIMPLE_RECURRING_REFINERS,
    
        });
        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 changeHandlerPlugin = createPlugin({
            optionChangeHandlers: {
                events: function (events, context) {
                    handleEventSources([events], context);
                },
    
                eventSources: handleEventSources,
            },
    
        });
        /*
        BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
        */
        function handleEventSources(inputs, context) {
            var unfoundSources = hashValuesToArray(context.getCurrentData().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 += 1) {
    
                    if (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];
                context.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];
                context.calendarApi.addEventSource(newInput);
            }
        }
    
        function handleDateProfile(dateProfile, context) {
            context.emitter.trigger('datesSet', __assign(__assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
        }
    
        function handleEventStore(eventStore, context) {
            var emitter = context.emitter;
            if (emitter.hasHandlers('eventsSet')) {
                emitter.trigger('eventsSet', buildEventApis(eventStore, context));
            }
        }
    
        /*
        this array is exposed on the root namespace so that UMD plugins can add to it.
        see the rollup-bundles script.
        */
        var globalPlugins = [
            arrayEventSourcePlugin,
            funcEventSourcePlugin,
            jsonFeedEventSourcePlugin,
            simpleRecurringEventsPlugin,
            changeHandlerPlugin,
            createPlugin({
    
                isLoadingFuncs: [
                    function (state) { return computeEventSourcesLoading(state.eventSources); },
                ],
    
                contentTypeHandlers: {
    
                    html: function () { return ({ render: injectHtml }); },
                    domNodes: function () { return ({ render: injectDomNodes }); },
    
                },
                propSetHandlers: {
                    dateProfile: handleDateProfile,
    
                    eventStore: handleEventStore,
                },
            }),
    
        function injectHtml(el, html) {
            el.innerHTML = html;
        }
        function injectDomNodes(el, domNodes) {
            var oldNodes = Array.prototype.slice.call(el.childNodes); // TODO: use array util
            var newNodes = Array.prototype.slice.call(domNodes); // TODO: use array util
            if (!isArraysEqual(oldNodes, newNodes)) {
                for (var _i = 0, newNodes_1 = newNodes; _i < newNodes_1.length; _i++) {
                    var newNode = newNodes_1[_i];
                    el.appendChild(newNode);
                }
                oldNodes.forEach(removeElement);
            }
        }
    
    
        var DelayedRunner = /** @class */ (function () {
            function DelayedRunner(drainedOption) {
                this.drainedOption = drainedOption;
                this.isRunning = false;
                this.isDirty = false;
                this.pauseDepths = {};
                this.timeoutId = 0;
            }
            DelayedRunner.prototype.request = function (delay) {
                this.isDirty = true;
                if (!this.isPaused()) {
                    this.clearTimeout();
                    if (delay == null) {
                        this.tryDrain();
                    }
                    else {
                        this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce
                        this.tryDrain.bind(this), delay);
                    }
                }
            };
            DelayedRunner.prototype.pause = function (scope) {
                if (scope === void 0) { scope = ''; }
                var pauseDepths = this.pauseDepths;
                pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
                this.clearTimeout();
            };
            DelayedRunner.prototype.resume = function (scope, force) {
                if (scope === void 0) { scope = ''; }
                var pauseDepths = this.pauseDepths;
                if (scope in pauseDepths) {
                    if (force) {
                        delete pauseDepths[scope];
                    }
                    else {
    
                        pauseDepths[scope] -= 1;
                        var depth = pauseDepths[scope];
    
                        if (depth <= 0) {
                            delete pauseDepths[scope];
                        }
                    }
                    this.tryDrain();
                }
            };
            DelayedRunner.prototype.isPaused = function () {
                return Object.keys(this.pauseDepths).length;
            };
            DelayedRunner.prototype.tryDrain = function () {
                if (!this.isRunning && !this.isPaused()) {
                    this.isRunning = true;
                    while (this.isDirty) {
                        this.isDirty = false;
                        this.drained(); // might set isDirty to true again
                    }
                    this.isRunning = false;
                }
            };
            DelayedRunner.prototype.clear = function () {
                this.clearTimeout();
                this.isDirty = false;
                this.pauseDepths = {};
            };
            DelayedRunner.prototype.clearTimeout = function () {
                if (this.timeoutId) {
                    clearTimeout(this.timeoutId);
                    this.timeoutId = 0;
                }
            };
            DelayedRunner.prototype.drained = function () {
                if (this.drainedOption) {
                    this.drainedOption();
                }
            };
            return DelayedRunner;
        }());
    
        var TaskRunner = /** @class */ (function () {
            function TaskRunner(runTaskOption, drainedOption) {
                this.runTaskOption = runTaskOption;
                this.drainedOption = drainedOption;
                this.queue = [];
                this.delayedRunner = new DelayedRunner(this.drain.bind(this));
            }
            TaskRunner.prototype.request = function (task, delay) {
                this.queue.push(task);
                this.delayedRunner.request(delay);
            };
            TaskRunner.prototype.pause = function (scope) {
                this.delayedRunner.pause(scope);
            };
            TaskRunner.prototype.resume = function (scope, force) {
                this.delayedRunner.resume(scope, force);
            };
            TaskRunner.prototype.drain = function () {
                var queue = this.queue;
                while (queue.length) {
                    var completedTasks = [];
                    var task = void 0;
                    while ((task = queue.shift())) {
                        this.runTask(task);
                        completedTasks.push(task);
                    }
                    this.drained(completedTasks);
                } // keep going, in case new tasks were added in the drained handler
            };
            TaskRunner.prototype.runTask = function (task) {
                if (this.runTaskOption) {
                    this.runTaskOption(task);
                }
            };
            TaskRunner.prototype.drained = function (completedTasks) {
                if (this.drainedOption) {
                    this.drainedOption(completedTasks);
                }
            };
            return TaskRunner;
        }());
    
        // Computes what the title at the top of the calendarApi should be for this view
        function buildTitle(dateProfile, viewOptions, dateEnv) {
            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;
            }
            return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
                isEndExclusive: dateProfile.isRangeAllDay,
    
                defaultSeparator: viewOptions.titleRangeSeparator,
    
            });
        }
        // 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 buildTitleFormat(dateProfile) {
            var currentRangeUnit = dateProfile.currentRangeUnit;
            if (currentRangeUnit === 'year') {
                return { year: 'numeric' };
            }
    
            if (currentRangeUnit === 'month') {
    
                return { year: 'numeric', month: 'long' }; // like "September 2014"
            }
    
            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' };
    
            // one day. longer, like "September 9 2014"
            return { year: 'numeric', month: 'long', day: 'numeric' };
    
        }
    
        // in future refactor, do the redux-style function(state=initial) for initial-state