aboutsummaryrefslogtreecommitdiffstats
path: root/library/fullcalendar/packages/core/main.js
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2020-06-15 08:19:13 +0000
committerMario <mario@mariovavti.com>2020-06-15 08:19:13 +0000
commit56ec55110a27a13cc2c7d1fb09f1650f8c4cd842 (patch)
tree1ed6199b0d09b232b3ba5dce28a0a0134242df55 /library/fullcalendar/packages/core/main.js
parent570497071d7dc231be6ab0eee951c22f1ad05df2 (diff)
downloadvolse-hubzilla-56ec55110a27a13cc2c7d1fb09f1650f8c4cd842.tar.gz
volse-hubzilla-56ec55110a27a13cc2c7d1fb09f1650f8c4cd842.tar.bz2
volse-hubzilla-56ec55110a27a13cc2c7d1fb09f1650f8c4cd842.zip
update fullcalendar to version 4.4.2
Diffstat (limited to 'library/fullcalendar/packages/core/main.js')
-rw-r--r--library/fullcalendar/packages/core/main.js1212
1 files changed, 583 insertions, 629 deletions
diff --git a/library/fullcalendar/packages/core/main.js b/library/fullcalendar/packages/core/main.js
index 8225f1a9e..2cb657a60 100644
--- a/library/fullcalendar/packages/core/main.js
+++ b/library/fullcalendar/packages/core/main.js
@@ -1,8 +1,9 @@
/*!
-FullCalendar Core Package v4.0.2
+FullCalendar Core Package v4.4.2
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
+
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -276,6 +277,7 @@ Docs & License: https://fullcalendar.io/
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 = {
@@ -337,9 +339,11 @@ Docs & License: https://fullcalendar.io/
};
}
function computeHeightAndMargins(el) {
+ return el.getBoundingClientRect().height + computeVMargins(el);
+ }
+ function computeVMargins(el) {
var computed = window.getComputedStyle(el);
- return el.getBoundingClientRect().height +
- parseInt(computed.marginTop, 10) +
+ return parseInt(computed.marginTop, 10) +
parseInt(computed.marginBottom, 10);
}
// does not return window
@@ -800,11 +804,12 @@ Docs & License: https://fullcalendar.io/
// 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 naturalOffset = computeHeightAndMargins(el);
+ var naturalHeight = el.getBoundingClientRect().height;
+ var naturalOffset = naturalHeight + computeVMargins(el);
if (naturalOffset < minOffset) {
flexEls.push(el);
flexOffsets.push(naturalOffset);
- flexHeights.push(el.offsetHeight);
+ flexHeights.push(naturalHeight);
}
else {
// this element stretches past recommended height (non-expandable). mark the space as occupied.
@@ -842,7 +847,7 @@ Docs & License: https://fullcalendar.io/
els.forEach(function (el) {
var innerEl = el.firstChild; // hopefully an element
if (innerEl instanceof HTMLElement) {
- var innerWidth_1 = innerEl.offsetWidth;
+ var innerWidth_1 = innerEl.getBoundingClientRect().width;
if (innerWidth_1 > maxInnerWidth) {
maxInnerWidth = innerWidth_1;
}
@@ -864,7 +869,9 @@ Docs & License: https://fullcalendar.io/
};
applyStyle(outerEl, reflowStyleProps);
applyStyle(innerEl, reflowStyleProps);
- var diff = outerEl.offsetHeight - innerEl.offsetHeight; // grab the dimensions
+ var diff = // grab the dimensions
+ outerEl.getBoundingClientRect().height -
+ innerEl.getBoundingClientRect().height;
// undo hack
var resetStyleProps = { position: '', left: '' };
applyStyle(outerEl, resetStyleProps);
@@ -1071,16 +1078,6 @@ Docs & License: https://fullcalendar.io/
}
return refined;
}
- /*
- Get a snapshot of an object, so we can compare it to later revisions.
- Intentionally only works with arrays, jaja
- */
- function freezeRaw(raw) {
- if (Array.isArray(raw)) {
- return Array.prototype.slice.call(raw);
- }
- return raw;
- }
/* Date stuff that doesn't belong in datelib core
----------------------------------------------------------------------------------------------------------------------*/
// given a timed range, computes an all-day range that has the same exact duration,
@@ -1134,18 +1131,18 @@ Docs & License: https://fullcalendar.io/
}
/*! *****************************************************************************
- Copyright (c) Microsoft Corporation. All rights reserved.
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- this file except in compliance with the License. You may obtain a copy of the
- License at http://www.apache.org/licenses/LICENSE-2.0
+ Copyright (c) Microsoft Corporation.
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
- MERCHANTABLITY OR NON-INFRINGEMENT.
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted.
- See the Apache Version 2.0 License for specific language governing permissions
- and limitations under the License.
+ 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.
***************************************************************************** */
/* global Reflect, Promise */
@@ -1203,9 +1200,12 @@ Docs & License: https://fullcalendar.io/
/*
Event MUST have a recurringDef
*/
- function expandRecurringRanges(eventDef, framingRange, dateEnv, recurringTypes) {
+ function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
var typeDef = recurringTypes[eventDef.recurringDef.typeId];
- var markers = typeDef.expand(eventDef.recurringDef.typeData, framingRange, dateEnv);
+ 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);
@@ -1213,6 +1213,7 @@ Docs & License: https://fullcalendar.io/
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) {
@@ -1286,6 +1287,23 @@ Docs & License: https://fullcalendar.io/
}
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();
@@ -1316,13 +1334,13 @@ Docs & License: https://fullcalendar.io/
for (var defId in defs) {
var def = defs[defId];
if (def.recurringDef) {
- var starts = expandRecurringRanges(def, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes);
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, {
@@ -2035,13 +2053,12 @@ Docs & License: https://fullcalendar.io/
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!?
- var endDelta = null;
if (options.maintainDuration) {
- var origDuration = diffDates(instanceRange.start, instanceRange.end, dateEnv, options.granularity);
- var newDuration = diffDates(start, instanceRange.end, dateEnv, options.granularity);
- endDelta = subtractDurations(origDuration, newDuration);
+ this.mutate({ datesDelta: startDelta });
+ }
+ else {
+ this.mutate({ startDelta: startDelta });
}
- this.mutate({ startDelta: startDelta, endDelta: endDelta });
}
};
EventApi.prototype.setEnd = function (endInput, options) {
@@ -2089,11 +2106,16 @@ Docs & License: https://fullcalendar.io/
var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
if (end) {
var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
- this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps });
+ if (durationsEqual(startDelta, endDelta)) {
+ this.mutate({ datesDelta: startDelta, standardProps: standardProps });
+ }
+ else {
+ this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps });
+ }
}
- else {
+ else { // means "clear the end"
standardProps.hasEnd = false;
- this.mutate({ startDelta: startDelta, standardProps: standardProps });
+ this.mutate({ datesDelta: startDelta, standardProps: standardProps });
}
}
};
@@ -2112,7 +2134,7 @@ Docs & License: https://fullcalendar.io/
EventApi.prototype.moveDates = function (deltaInput) {
var delta = createDuration(deltaInput);
if (delta) { // TODO: warning if parsed bad
- this.mutate({ startDelta: delta, endDelta: delta });
+ this.mutate({ datesDelta: delta });
}
};
EventApi.prototype.setAllDay = function (allDay, options) {
@@ -2370,12 +2392,13 @@ Docs & License: https://fullcalendar.io/
function hasBgRendering(def) {
return def.rendering === 'background' || def.rendering === 'inverse-background';
}
- function filterSegsViaEls(view, segs, isMirror) {
- if (view.hasPublicHandlers('eventRender')) {
+ function filterSegsViaEls(context, segs, isMirror) {
+ var calendar = context.calendar, view = context.view;
+ if (calendar.hasPublicHandlers('eventRender')) {
segs = segs.filter(function (seg) {
- var custom = view.publiclyTrigger('eventRender', [
+ var custom = calendar.publiclyTrigger('eventRender', [
{
- event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance),
+ event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
isMirror: isMirror,
isStart: seg.isStart,
isEnd: seg.isEnd,
@@ -2422,6 +2445,65 @@ Docs & License: https://fullcalendar.io/
uis.push(eventDef.ui);
return combineEventUis(uis);
}
+ // 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
+ }
+ ]);
+ }
+ }
+ if (!calendar.state.eventSourceLoadingLevel) { // avoid initial empty state while pending
+ 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;
+ }
// applies the mutation to ALL defs/instances within the event store
function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) {
@@ -2445,7 +2527,7 @@ Docs & License: https://fullcalendar.io/
// and thus, we need to mark the event as having a real end
if (standardProps.hasEnd == null &&
eventConfig.durationEditable &&
- willDeltasAffectDuration(eventConfig.startEditable ? mutation.startDelta : null, mutation.endDelta || null)) {
+ (mutation.startDelta || mutation.endDelta)) {
standardProps.hasEnd = true; // TODO: is this mutation okay?
}
var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) });
@@ -2461,21 +2543,6 @@ Docs & License: https://fullcalendar.io/
}
return copy;
}
- function willDeltasAffectDuration(startDelta, endDelta) {
- if (startDelta && !asRoughMs(startDelta)) {
- startDelta = null;
- }
- if (endDelta && !asRoughMs(endDelta)) {
- endDelta = null;
- }
- if (!startDelta && !endDelta) {
- return false;
- }
- if (Boolean(startDelta) !== Boolean(endDelta)) {
- return true;
- }
- return !durationsEqual(startDelta, endDelta);
- }
function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
eventConfig, mutation, calendar) {
var dateEnv = calendar.dateEnv;
@@ -2485,25 +2552,28 @@ Docs & License: https://fullcalendar.io/
if (forceAllDay) {
copy.range = computeAlignedDayRange(copy.range);
}
- if (mutation.startDelta && eventConfig.startEditable) {
+ 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 (clearEnd) {
+ if (mutation.endDelta && eventConfig.durationEditable) {
copy.range = {
start: copy.range.start,
- end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start)
+ end: dateEnv.add(copy.range.end, mutation.endDelta)
};
}
- else if (mutation.endDelta &&
- (eventConfig.durationEditable ||
- !willDeltasAffectDuration(// TODO: nonDRY logic above
- eventConfig.startEditable ? mutation.startDelta : null, mutation.endDelta))) {
+ if (clearEnd) {
copy.range = {
start: copy.range.start,
- end: dateEnv.add(copy.range.end, mutation.endDelta)
+ end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start)
};
}
// in case event was all-day but the supplied deltas were not
@@ -2709,11 +2779,12 @@ Docs & License: https://fullcalendar.io/
}
}
// 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 = state.eventStore.defs[subjectDef.defId];
- var origInstance = state.eventStore.instances[subjectInstanceId];
+ 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);
@@ -3187,90 +3258,6 @@ Docs & License: https://fullcalendar.io/
return res;
}
- function isValuesSimilar(val0, val1, depth) {
- if (depth === void 0) { depth = 1; }
- if (val0 === val1) {
- return true;
- }
- else if (Array.isArray(val0) && Array.isArray(val1)) {
- return isArraysSimilar(val0, val1, depth);
- }
- else if (typeof val0 === 'object' && val0 && typeof val1 === 'object' && val1) { // non-null objects
- return isObjectsSimilar(val0, val1, depth);
- }
- else {
- return false;
- }
- }
- function isArraysSimilar(a0, a1, depth) {
- if (depth === void 0) { depth = 1; }
- if (a0 === a1) {
- return true;
- }
- else if (depth > 0) {
- if (a0.length !== a1.length) {
- return false;
- }
- else {
- for (var i = 0; i < a0.length; i++) {
- if (!isValuesSimilar(a0[i], a1[i], depth - 1)) {
- return false;
- }
- }
- return true;
- }
- }
- else {
- return false;
- }
- }
- function isObjectsSimilar(obj0, obj1, depth) {
- if (depth === void 0) { depth = 1; }
- if (obj0 === obj1) {
- return true;
- }
- else if (depth > 0) {
- for (var prop in obj0) {
- if (!(prop in obj1)) {
- return false;
- }
- }
- for (var prop in obj1) {
- if (!(prop in obj0)) {
- return false;
- }
- else {
- if (!isValuesSimilar(obj0[prop], obj1[prop], depth - 1)) {
- return false;
- }
- }
- }
- return true;
- }
- else {
- return false;
- }
- }
- function computeChangedProps(obj0, obj1, depth) {
- if (depth === void 0) { depth = 1; }
- var res = {};
- for (var prop in obj1) {
- if (!(prop in obj0) ||
- !isValuesSimilar(obj0[prop], obj1[prop], depth - 1)) {
- res[prop] = obj1[prop];
- }
- }
- return res;
- }
- function anyKeysRemoved(obj0, obj1) {
- for (var prop in obj0) {
- if (!(prop in obj1)) {
- return true;
- }
- }
- return false;
- }
-
var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
var Splitter = /** @class */ (function () {
function Splitter() {
@@ -3418,8 +3405,7 @@ Docs & License: https://fullcalendar.io/
// { 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.
- function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) {
- var dateEnv = component.dateEnv;
+ function buildGotoAnchorHtml(allOptions, dateEnv, gotoOptions, attrs, innerHtml) {
var date;
var type;
var forceOff;
@@ -3442,7 +3428,7 @@ Docs & License: https://fullcalendar.io/
}
attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space
innerHtml = innerHtml || '';
- if (!forceOff && component.opt('navLinks')) {
+ if (!forceOff && allOptions.navLinks) {
return '<a' + attrs +
' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
innerHtml +
@@ -3454,12 +3440,12 @@ Docs & License: https://fullcalendar.io/
'</span>';
}
}
- function getAllDayHtml(component) {
- return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText'));
+ function getAllDayHtml(allOptions) {
+ return allOptions.allDayHtml || htmlEscape(allOptions.allDayText);
}
// Computes HTML classNames for a single-day element
function getDayClasses(date, dateProfile, context, noThemeHighlight) {
- var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv;
+ var calendar = context.calendar, options = context.options, theme = context.theme, dateEnv = context.dateEnv;
var classes = [];
var todayStart;
var todayEnd;
@@ -3468,7 +3454,7 @@ Docs & License: https://fullcalendar.io/
}
else {
classes.push('fc-' + DAY_IDS[date.getUTCDay()]);
- if (view.opt('monthMode') &&
+ if (options.monthMode &&
dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) {
classes.push('fc-other-month');
}
@@ -3933,34 +3919,59 @@ Docs & License: https://fullcalendar.io/
Theme.prototype.iconOverridePrefix = '';
var guid = 0;
+ 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;
+ }());
var Component = /** @class */ (function () {
- function Component(context, isView) {
- // HACK to populate view at top of component instantiation call chain
- if (isView) {
- context.view = this;
- }
+ function Component() {
+ this.everRendered = false;
this.uid = String(guid++);
- this.context = context;
- this.dateEnv = context.dateEnv;
- this.theme = context.theme;
- this.view = context.view;
- this.calendar = context.calendar;
- this.isRtl = this.opt('dir') === 'rtl';
}
Component.addEqualityFuncs = function (newFuncs) {
this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs);
};
- Component.prototype.opt = function (name) {
- return this.context.options[name];
- };
- Component.prototype.receiveProps = function (props) {
+ Component.prototype.receiveProps = function (props, context) {
+ this.receiveContext(context);
var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps;
this.props = comboProps;
if (anyChanges) {
- this.render(comboProps);
+ if (this.everRendered) {
+ this.beforeUpdate();
+ }
+ this.render(comboProps, context);
+ if (this.everRendered) {
+ this.afterUpdate();
+ }
+ }
+ this.everRendered = true;
+ };
+ Component.prototype.receiveContext = function (context) {
+ var oldContext = this.context;
+ this.context = context;
+ if (!oldContext) {
+ this.firstContext(context);
}
};
- Component.prototype.render = function (props) {
+ Component.prototype.render = function (props, context) {
+ };
+ Component.prototype.firstContext = function (context) {
+ };
+ Component.prototype.beforeUpdate = function () {
+ };
+ Component.prototype.afterUpdate = function () {
};
// after destroy is called, this component won't ever be used again
Component.prototype.destroy = function () {
@@ -4002,8 +4013,8 @@ Docs & License: https://fullcalendar.io/
*/
var DateComponent = /** @class */ (function (_super) {
__extends(DateComponent, _super);
- function DateComponent(context, el, isView) {
- var _this = _super.call(this, context, isView) || this;
+ function DateComponent(el) {
+ var _this = _super.call(this) || this;
_this.el = el;
return _this;
}
@@ -4011,47 +4022,17 @@ Docs & License: https://fullcalendar.io/
_super.prototype.destroy.call(this);
removeElement(this.el);
};
- // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror)
- //
- // Event Drag-n-Drop Rendering (for both events and external elements)
- // ---------------------------------------------------------------------------------------------------------------
- /*
- renderEventDragSegs(state: EventSegUiInteractionState) {
- if (state) {
- let { isEvent, segs, sourceSeg } = state
-
- if (this.eventRenderer) {
- this.eventRenderer.hideByHash(state.affectedInstances)
- }
-
- // if the user is dragging something that is considered an event with real event data,
- // and this component likes to do drag mirrors OR the component where the seg came from
- // likes to do drag mirrors, then render a drag mirror.
- if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) {
- if (this.mirrorRenderer) {
- this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg })
- }
- }
-
- // if it would be impossible to render a drag mirror OR this component likes to render
- // highlights, then render a highlight.
- if (!isEvent || this.doesDragHighlight) {
- if (this.fillRenderer) {
- this.fillRenderer.renderSegs('highlight', segs)
- }
- }
- }
- }
- */
// 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) {
- var calendar = this.calendar;
+ var calendar = this.context.calendar;
var dateProfile = this.props.dateProfile; // HACK
var instances = interaction.mutatedEvents.instances;
if (dateProfile) { // HACK for DayTile
@@ -4064,68 +4045,13 @@ Docs & License: https://fullcalendar.io/
return isInteractionValid(interaction, calendar);
};
DateComponent.prototype.isDateSelectionValid = function (selection) {
+ var calendar = this.context.calendar;
var dateProfile = this.props.dateProfile; // HACK
if (dateProfile && // HACK for DayTile
!rangeContainsRange(dateProfile.validRange, selection.range)) {
return false;
}
- return isDateSelectionValid(selection, this.calendar);
- };
- // Triggering
- // -----------------------------------------------------------------------------------------------------------------
- // TODO: move to Calendar
- DateComponent.prototype.publiclyTrigger = function (name, args) {
- var calendar = this.calendar;
- return calendar.publiclyTrigger(name, args);
- };
- DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) {
- var calendar = this.calendar;
- return calendar.publiclyTriggerAfterSizing(name, args);
- };
- DateComponent.prototype.hasPublicHandlers = function (name) {
- var calendar = this.calendar;
- return calendar.hasPublicHandlers(name);
- };
- DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) {
- var calendar = this.calendar;
- if (this.hasPublicHandlers('eventPositioned')) {
- for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
- var seg = segs_1[_i];
- this.publiclyTriggerAfterSizing('eventPositioned', [
- {
- event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
- isMirror: isMirrors,
- isStart: seg.isStart,
- isEnd: seg.isEnd,
- el: seg.el,
- view: this // ?
- }
- ]);
- }
- }
- if (!calendar.state.loadingLevel) { // avoid initial empty state while pending
- calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once
- }
- };
- DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) {
- var calendar = this.calendar;
- for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
- var seg = segs_2[_i];
- calendar.trigger('eventElRemove', seg.el);
- }
- if (this.hasPublicHandlers('eventDestroy')) {
- for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) {
- var seg = segs_3[_a];
- this.publiclyTrigger('eventDestroy', [
- {
- event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
- isMirror: isMirrors,
- el: seg.el,
- view: this // ?
- }
- ]);
- }
- }
+ return isDateSelectionValid(selection, calendar);
};
// Pointer Interaction Utils
// -----------------------------------------------------------------------------------------------------------------
@@ -4162,6 +4088,7 @@ Docs & License: https://fullcalendar.io/
deps: input.deps || [],
reducers: input.reducers || [],
eventDefParsers: input.eventDefParsers || [],
+ isDraggableTransformers: input.isDraggableTransformers || [],
eventDragMutationMassagers: input.eventDragMutationMassagers || [],
eventDefMutationAppliers: input.eventDefMutationAppliers || [],
dateSelectionTransformers: input.dateSelectionTransformers || [],
@@ -4191,6 +4118,7 @@ Docs & License: https://fullcalendar.io/
this.hooks = {
reducers: [],
eventDefParsers: [],
+ isDraggableTransformers: [],
eventDragMutationMassagers: [],
eventDefMutationAppliers: [],
dateSelectionTransformers: [],
@@ -4232,6 +4160,7 @@ Docs & License: https://fullcalendar.io/
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),
@@ -4439,11 +4368,17 @@ Docs & License: https://fullcalendar.io/
}
}
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: (props.startTime && props.endTime) ?
- subtractDurations(props.endTime, props.startTime) :
- null,
+ duration: duration,
typeData: props // doesn't need endTime anymore but oh well
};
}
@@ -4488,21 +4423,21 @@ Docs & License: https://fullcalendar.io/
var DefaultOptionChangeHandlers = createPlugin({
optionChangeHandlers: {
- events: function (events, calendar) {
- handleEventSources([events], calendar);
+ events: function (events, calendar, deepEqual) {
+ handleEventSources([events], calendar, deepEqual);
},
eventSources: handleEventSources,
plugins: handlePlugins
}
});
- function handleEventSources(inputs, calendar) {
+ 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 (isValuesSimilar(unfoundSources[i]._raw, input, 2)) {
+ if (deepEqual(unfoundSources[i]._raw, input)) {
unfoundSources.splice(i, 1); // delete
inputFound = true;
break;
@@ -4730,16 +4665,16 @@ Docs & License: https://fullcalendar.io/
this.dynamicOverrides = {};
this.compute();
}
- OptionsManager.prototype.add = function (props) {
- __assign(this.overrides, props);
- this.compute();
- };
- OptionsManager.prototype.addDynamic = function (props) {
- __assign(this.dynamicOverrides, props);
- this.compute();
- };
- OptionsManager.prototype.reset = function (props) {
- this.overrides = props;
+ OptionsManager.prototype.mutate = function (updates, removals, isDynamic) {
+ if (!Object.keys(updates).length && !removals.length) {
+ return;
+ }
+ 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`.
@@ -4797,39 +4732,25 @@ Docs & License: https://fullcalendar.io/
}());
registerCalendarSystem('gregory', GregorianCalendarSystem);
- var ISO_START = /^\s*\d{4}-\d\d-\d\d([T ]\d)?/;
- var ISO_TZO_RE = /(?:(Z)|([-+])(\d\d)(?::(\d\d))?)$/;
+ 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 timeZoneOffset = null;
- var isTimeUnspecified = false;
- var m = ISO_START.exec(str);
+ var m = ISO_RE.exec(str);
if (m) {
- isTimeUnspecified = !m[1];
- if (isTimeUnspecified) {
- str += 'T00:00:00Z';
- }
- else {
- str = str.replace(ISO_TZO_RE, function (whole, z, sign, minutes, seconds) {
- if (z) {
- timeZoneOffset = 0;
- }
- else {
- timeZoneOffset = (parseInt(minutes, 10) * 60 +
- parseInt(seconds || 0, 10)) * (sign === '-' ? -1 : 1);
- }
- return '';
- }) + 'Z'; // otherwise will parse in local
+ 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
+ };
}
}
- var marker = new Date(str);
- if (!isValidDate(marker)) {
- return null;
- }
- return {
- marker: marker,
- isTimeUnspecified: isTimeUnspecified,
- timeZoneOffset: timeZoneOffset
- };
+ return null;
}
var DateEnv = /** @class */ (function () {
@@ -4848,7 +4769,7 @@ Docs & License: https://fullcalendar.io/
this.weekDow = 1;
this.weekDoy = 4;
}
- else if (typeof settings.firstDay === 'number') {
+ if (typeof settings.firstDay === 'number') {
this.weekDow = settings.firstDay;
}
if (typeof settings.weekNumberCalculation === 'function') {
@@ -5176,7 +5097,7 @@ Docs & License: https://fullcalendar.io/
var meta = def.parseMeta(raw);
if (meta) {
var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar);
- res._raw = freezeRaw(raw);
+ res._raw = raw;
return res;
}
}
@@ -5258,6 +5179,7 @@ Docs & License: https://fullcalendar.io/
else {
return !calendar.opt('lazyFetching') ||
!eventSource.fetchRange ||
+ eventSource.isFetching || // always cancel outdated in-progress fetches
fetchRange.start < eventSource.fetchRange.start ||
fetchRange.end > eventSource.fetchRange.end;
}
@@ -5325,7 +5247,8 @@ Docs & License: https://fullcalendar.io/
var eventSource = sourceHash[sourceId];
if (eventSource && // not already removed
fetchId === eventSource.latestFetchId) {
- return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a));
+ 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));
}
return sourceHash;
}
@@ -5662,10 +5585,19 @@ Docs & License: https://fullcalendar.io/
}());
// TODO: find a way to avoid comparing DateProfiles. it's tedious
function isDateProfilesEqual(p0, p1) {
- return rangesEqual(p0.activeRange, p1.activeRange) &&
- rangesEqual(p0.validRange, p1.validRange) &&
+ 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) {
@@ -5941,7 +5873,13 @@ Docs & License: https://fullcalendar.io/
findViewNameBySubclass(theClass, overrideConfigs) ||
findViewNameBySubclass(theClass, defaultConfigs);
}
- var superDef = superType ? ensureViewDef(superType, hash, defaultConfigs, overrideConfigs) : null;
+ 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;
}
@@ -6048,8 +5986,8 @@ Docs & License: https://fullcalendar.io/
var Toolbar = /** @class */ (function (_super) {
__extends(Toolbar, _super);
- function Toolbar(context, extraClassName) {
- var _this = _super.call(this, context) || this;
+ function Toolbar(extraClassName) {
+ var _this = _super.call(this) || this;
_this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout);
_this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]);
_this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]);
@@ -6084,7 +6022,7 @@ Docs & License: https://fullcalendar.io/
};
Toolbar.prototype.renderSection = function (position, buttonStr) {
var _this = this;
- var _a = this, theme = _a.theme, calendar = _a.calendar;
+ var _a = this.context, theme = _a.theme, calendar = _a.calendar;
var optionsManager = calendar.optionsManager;
var viewSpecs = calendar.viewSpecs;
var sectionEl = createElement('div', { className: 'fc-' + position });
@@ -6192,7 +6130,8 @@ Docs & License: https://fullcalendar.io/
});
};
Toolbar.prototype.updateActiveButton = function (buttonName) {
- var className = this.theme.getClass('buttonActive');
+ var theme = this.context.theme;
+ var className = theme.getClass('buttonActive');
findElements(this.el, 'button').forEach(function (buttonEl) {
if (buttonName && buttonEl.classList.contains('fc-' + buttonName + '-button')) {
buttonEl.classList.add(className);
@@ -6212,24 +6151,29 @@ Docs & License: https://fullcalendar.io/
var CalendarComponent = /** @class */ (function (_super) {
__extends(CalendarComponent, _super);
- function CalendarComponent(context, el) {
- var _this = _super.call(this, context) || this;
- _this._renderToolbars = memoizeRendering(_this.renderToolbars);
+ 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);
_this.buildViewPropTransformers = memoize(buildViewPropTransformers);
_this.el = el;
- prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' }));
- var calendar = _this.calendar;
- for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) {
- var modifyViewContainer = _a[_i];
- modifyViewContainer(_this.contentEl, calendar);
- }
- _this.toggleElClassNames(true);
_this.computeTitle = memoize(computeTitle);
_this.parseBusinessHours = memoize(function (input) {
- return parseBusinessHours(input, _this.calendar);
+ return parseBusinessHours(input, _this.context.calendar);
});
return _this;
}
+ 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();
+ };
CalendarComponent.prototype.destroy = function () {
if (this.header) {
this.header.destroy();
@@ -6237,40 +6181,57 @@ Docs & License: https://fullcalendar.io/
if (this.footer) {
this.footer.destroy();
}
+ 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
if (this.view) {
+ this.savedScroll = this.view.queryScroll();
this.view.destroy();
+ this.view = null;
}
removeElement(this.contentEl);
- this.toggleElClassNames(false);
- _super.prototype.destroy.call(this);
+ this.removeElClassNames();
};
- CalendarComponent.prototype.toggleElClassNames = function (bool) {
+ CalendarComponent.prototype.removeElClassNames = function () {
var classList = this.el.classList;
- var dirClassName = 'fc-' + this.opt('dir');
- var themeClassName = this.theme.getClass('widget');
- if (bool) {
- classList.add('fc');
- classList.add(dirClassName);
- classList.add(themeClassName);
- }
- else {
- classList.remove('fc');
- classList.remove(dirClassName);
- classList.remove(themeClassName);
- }
- };
- CalendarComponent.prototype.render = function (props) {
- this.freezeHeight();
- var title = this.computeTitle(props.dateProfile, props.viewSpec.options);
- this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title);
- this.renderView(props, title);
- this.updateSize();
- this.thawHeight();
- };
- CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) {
- var headerLayout = this.opt('header');
- var footerLayout = this.opt('footer');
- var now = this.calendar.getNow();
+ 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();
var todayInfo = dateProfileGenerator.build(now);
var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate);
var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate);
@@ -6282,48 +6243,55 @@ Docs & License: https://fullcalendar.io/
isNextEnabled: nextInfo.isValid
};
if (headerLayout) {
- if (!this.header) {
- this.header = new Toolbar(this.context, 'fc-header-toolbar');
- prependToElement(this.el, this.header.el);
+ if (!header) {
+ header = this.header = new Toolbar('fc-header-toolbar');
+ prependToElement(this.el, header.el);
}
- this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps));
+ header.receiveProps(__assign({ layout: headerLayout }, toolbarProps), context);
}
- else if (this.header) {
- this.header.destroy();
- this.header = null;
+ else if (header) {
+ header.destroy();
+ header = this.header = null;
}
if (footerLayout) {
- if (!this.footer) {
- this.footer = new Toolbar(this.context, 'fc-footer-toolbar');
- appendToElement(this.el, this.footer.el);
+ if (!footer) {
+ footer = this.footer = new Toolbar('fc-footer-toolbar');
+ appendToElement(this.el, footer.el);
}
- this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps));
+ 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;
}
- else if (this.footer) {
+ if (this.footer) {
this.footer.destroy();
this.footer = null;
}
};
CalendarComponent.prototype.renderView = function (props, title) {
var view = this.view;
+ var _a = this.context, calendar = _a.calendar, options = _a.options;
var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator;
if (!view || view.viewSpec !== viewSpec) {
if (view) {
view.destroy();
}
- view = this.view = new viewSpec['class']({
- calendar: this.calendar,
- view: null,
- dateEnv: this.dateEnv,
- theme: this.theme,
- options: viewSpec.options
- }, viewSpec, dateProfileGenerator, this.contentEl);
- }
- else {
- view.addScroll(view.queryScroll());
+ view = this.view = new viewSpec['class'](viewSpec, this.contentEl);
+ if (this.savedScroll) {
+ view.addScroll(this.savedScroll, true);
+ this.savedScroll = null;
+ }
}
view.title = title; // for the API
var viewProps = {
+ dateProfileGenerator: dateProfileGenerator,
dateProfile: props.dateProfile,
businessHours: this.parseBusinessHours(viewSpec.options.businessHours),
eventStore: props.eventStore,
@@ -6333,20 +6301,20 @@ Docs & License: https://fullcalendar.io/
eventDrag: props.eventDrag,
eventResize: props.eventResize
};
- var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers);
+ var transformers = this.buildViewPropTransformers(calendar.pluginSystem.hooks.viewPropsTransformers);
for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
var transformer = transformers_1[_i];
- __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view));
+ __assign(viewProps, transformer.transform(viewProps, viewSpec, props, options));
}
- view.receiveProps(viewProps);
+ view.receiveProps(viewProps, this.buildComponentContext(this.context, viewSpec, view));
};
// Sizing
// -----------------------------------------------------------------------------------------------------------------
CalendarComponent.prototype.updateSize = function (isResize) {
if (isResize === void 0) { isResize = false; }
var view = this.view;
- if (isResize) {
- view.addScroll(view.queryScroll());
+ if (!view) {
+ return; // why?
}
if (isResize || this.isHeightAuto == null) {
this.computeHeightVars();
@@ -6356,7 +6324,7 @@ Docs & License: https://fullcalendar.io/
view.popScroll(isResize);
};
CalendarComponent.prototype.computeHeightVars = function () {
- var calendar = this.calendar; // yuck. need to handle dynamic options
+ var calendar = this.context.calendar; // yuck. need to handle dynamic options
var heightInput = calendar.opt('height');
var contentHeightInput = calendar.opt('contentHeight');
this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto';
@@ -6373,10 +6341,11 @@ Docs & License: https://fullcalendar.io/
this.viewHeight = heightInput() - this.queryToolbarsHeight();
}
else if (heightInput === 'parent') { // set to height of parent element
- this.viewHeight = this.el.parentNode.offsetHeight - this.queryToolbarsHeight();
+ var parentEl = this.el.parentNode;
+ this.viewHeight = parentEl.getBoundingClientRect().height - this.queryToolbarsHeight();
}
else {
- this.viewHeight = Math.round(this.contentEl.offsetWidth /
+ this.viewHeight = Math.round(this.contentEl.getBoundingClientRect().width /
Math.max(calendar.opt('aspectRatio'), .5));
}
};
@@ -6394,7 +6363,7 @@ Docs & License: https://fullcalendar.io/
// -----------------------------------------------------------------------------------------------------------------
CalendarComponent.prototype.freezeHeight = function () {
applyStyle(this.el, {
- height: this.el.offsetHeight,
+ height: this.el.getBoundingClientRect().height,
overflow: 'hidden'
});
};
@@ -6418,7 +6387,7 @@ Docs & License: https://fullcalendar.io/
else { // for day units or smaller, use the actual day range
range = dateProfile.activeRange;
}
- return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay });
+ return this.context.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay });
}
// 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`.
@@ -6442,6 +6411,10 @@ Docs & License: https://fullcalendar.io/
}
}
}
+ // build a context scoped to the view
+ function buildComponentContext(context, viewSpec, view) {
+ return context.extend(viewSpec.options, view);
+ }
// Plugin
// -----------------------------------------------------------------------------------------------------------------
function buildViewPropTransformers(theClasses) {
@@ -6483,6 +6456,7 @@ Docs & License: https://fullcalendar.io/
var _this = _super.call(this, settings) || this;
_this.handleSegClick = function (ev, segEl) {
var component = _this.component;
+ var _a = component.context, calendar = _a.calendar, view = _a.view;
var seg = getElSeg(segEl);
if (seg && // might be the <div> surrounding the more link
component.isValidSegDownEl(ev.target)) {
@@ -6490,12 +6464,12 @@ Docs & License: https://fullcalendar.io/
// 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 : '';
- component.publiclyTrigger('eventClick', [
+ calendar.publiclyTrigger('eventClick', [
{
el: segEl,
- event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance),
+ event: new EventApi(component.context.calendar, seg.eventRange.def, seg.eventRange.instance),
jsEvent: ev,
- view: component.view
+ view: view
}
]);
if (url && !ev.defaultPrevented) {
@@ -6540,23 +6514,25 @@ Docs & License: https://fullcalendar.io/
};
var component = settings.component;
_this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave);
- component.calendar.on('eventElRemove', _this.handleEventElRemove);
+ // how to make sure component already has context?
+ component.context.calendar.on('eventElRemove', _this.handleEventElRemove);
return _this;
}
EventHovering.prototype.destroy = function () {
this.removeHoverListeners();
- this.component.calendar.off('eventElRemove', this.handleEventElRemove);
+ this.component.context.calendar.off('eventElRemove', this.handleEventElRemove);
};
EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) {
var component = this.component;
+ var _a = component.context, calendar = _a.calendar, view = _a.view;
var seg = getElSeg(segEl);
if (!ev || component.isValidSegDownEl(ev.target)) {
- component.publiclyTrigger(publicEvName, [
+ calendar.publiclyTrigger(publicEvName, [
{
el: segEl,
- event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance),
+ event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
jsEvent: ev,
- view: component.view
+ view: view
}
]);
}
@@ -6601,20 +6577,20 @@ Docs & License: https://fullcalendar.io/
var Calendar = /** @class */ (function () {
function Calendar(el, overrides) {
var _this = this;
+ this.buildComponentContext = memoize(buildComponentContext$1);
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, isObjectsSimilar);
+ 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.needsFullRerender = false;
this.isRendering = false; // currently in the executeRender function?
this.renderingPauseDepth = 0;
this.buildDelayedRerender = memoize(buildDelayedRerender);
@@ -6654,12 +6630,13 @@ Docs & License: https://fullcalendar.io/
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.render = function () {
if (!this.component) {
+ this.component = new CalendarComponent(this.el);
this.renderableEventStore = createEmptyEventStore();
this.bindHandlers();
this.executeRender();
}
else {
- this.requestRerender(true);
+ this.requestRerender();
}
};
Calendar.prototype.destroy = function () {
@@ -6768,12 +6745,12 @@ Docs & License: https://fullcalendar.io/
this.publiclyTrigger('loading', [false]);
}
var view = this.component && this.component.view;
- if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) {
+ if (oldState.eventStore !== newState.eventStore) {
if (oldState.eventStore) {
this.isEventsUpdated = true;
}
}
- if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) {
+ if (oldState.dateProfile !== newState.dateProfile) {
if (oldState.dateProfile && view) { // why would view be null!?
this.publiclyTrigger('datesDestroy', [
{
@@ -6784,7 +6761,7 @@ Docs & License: https://fullcalendar.io/
}
this.isDatesUpdated = true;
}
- if (oldState.viewType !== newState.viewType || this.needsFullRerender) {
+ if (oldState.viewType !== newState.viewType) {
if (oldState.viewType && view) { // why would view be null!?
this.publiclyTrigger('viewSkeletonDestroy', [
{
@@ -6803,10 +6780,8 @@ Docs & License: https://fullcalendar.io/
};
// Render Queue
// -----------------------------------------------------------------------------------------------------------------
- Calendar.prototype.requestRerender = function (needsFull) {
- if (needsFull === void 0) { needsFull = false; }
+ Calendar.prototype.requestRerender = function () {
this.needsRerender = true;
- this.needsFullRerender = this.needsFullRerender || needsFull;
this.delayedRerender(); // will call a debounced-version of tryRerender
};
Calendar.prototype.tryRerender = function () {
@@ -6829,12 +6804,10 @@ Docs & License: https://fullcalendar.io/
// Rendering
// -----------------------------------------------------------------------------------------------------------------
Calendar.prototype.executeRender = function () {
- var needsFullRerender = this.needsFullRerender; // save before clearing
// clear these BEFORE the render so that new values will accumulate during render
this.needsRerender = false;
- this.needsFullRerender = false;
this.isRendering = true;
- this.renderComponent(needsFullRerender);
+ this.renderComponent();
this.isRendering = false;
// received a rerender request while rendering
if (this.needsRerender) {
@@ -6844,11 +6817,10 @@ Docs & License: https://fullcalendar.io/
/*
don't call this directly. use executeRender instead
*/
- Calendar.prototype.renderComponent = function (needsFull) {
+ Calendar.prototype.renderComponent = function () {
var _a = this, state = _a.state, component = _a.component;
var viewType = state.viewType;
var viewSpec = this.viewSpecs[viewType];
- var savedScroll = (needsFull && component) ? component.view.queryScroll() : null;
if (!viewSpec) {
throw new Error("View type \"" + viewType + "\" is not valid");
}
@@ -6861,23 +6833,7 @@ Docs & License: https://fullcalendar.io/
var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options);
var eventUiBySource = this.buildEventUiBySource(state.eventSources);
var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
- if (needsFull || !component) {
- if (component) {
- component.freezeHeight(); // next component will unfreeze it
- component.destroy();
- }
- component = this.component = new CalendarComponent({
- calendar: this,
- view: null,
- dateEnv: this.dateEnv,
- theme: this.theme,
- options: this.optionsManager.computed
- }, this.el);
- }
- component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfile: state.dateProfile, dateProfileGenerator: this.dateProfileGenerators[viewType], eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize }));
- if (savedScroll) {
- component.view.applyScroll(savedScroll, false);
- }
+ 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));
if (this.isViewUpdated) {
this.isViewUpdated = false;
this.publiclyTrigger('viewSkeletonRender', [
@@ -6903,98 +6859,60 @@ Docs & License: https://fullcalendar.io/
};
// Options
// -----------------------------------------------------------------------------------------------------------------
- /*
- Not meant for public API
- */
- Calendar.prototype.resetOptions = function (options) {
- var _this = this;
- var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers;
- var oldOptions = this.optionsManager.overrides;
- var oldNormalOptions = {};
- var normalOptions = {};
- var specialOptions = {};
- for (var name_1 in oldOptions) {
- if (!changeHandlers[name_1]) {
- oldNormalOptions[name_1] = oldOptions[name_1];
- }
- }
- for (var name_2 in options) {
- if (changeHandlers[name_2]) {
- specialOptions[name_2] = options[name_2];
- }
- else {
- normalOptions[name_2] = options[name_2];
- }
- }
- this.batchRendering(function () {
- if (anyKeysRemoved(oldNormalOptions, normalOptions)) {
- _this.processOptions(options, 'reset');
- }
- else {
- _this.processOptions(computeChangedProps(oldNormalOptions, normalOptions));
- }
- // handle special options last
- for (var name_3 in specialOptions) {
- changeHandlers[name_3](specialOptions[name_3], _this);
- }
- });
+ 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;
};
/*
- Not meant for public API. Won't give the same precedence that setOption does
+ handles option changes (like a diff)
*/
- Calendar.prototype.setOptions = function (options) {
+ Calendar.prototype.mutateOptions = function (updates, removals, isDynamic, deepEqual) {
var _this = this;
var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers;
- var normalOptions = {};
- var specialOptions = {};
- for (var name_4 in options) {
- if (changeHandlers[name_4]) {
- specialOptions[name_4] = options[name_4];
+ 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 {
- normalOptions[name_4] = options[name_4];
+ normalUpdates[name_1] = updates[name_1];
}
}
- this.batchRendering(function () {
- _this.processOptions(normalOptions);
- // handle special options last
- for (var name_5 in specialOptions) {
- changeHandlers[name_5](specialOptions[name_5], _this);
- }
- });
- };
- Calendar.prototype.processOptions = function (options, mode) {
- var _this = this;
- var oldDateEnv = this.dateEnv; // do this before handleOptions
- var isTimeZoneDirty = false;
- var isSizeDirty = false;
- var anyDifficultOptions = false;
- for (var name_6 in options) {
- if (/^(height|contentHeight|aspectRatio)$/.test(name_6)) {
+ for (var name_2 in normalUpdates) {
+ if (/^(height|contentHeight|aspectRatio)$/.test(name_2)) {
isSizeDirty = true;
}
- else if (/^(defaultDate|defaultView)$/.test(name_6)) ;
+ else if (/^(defaultDate|defaultView)$/.test(name_2)) ;
else {
anyDifficultOptions = true;
- if (name_6 === 'timeZone') {
+ if (name_2 === 'timeZone') {
isTimeZoneDirty = true;
}
}
}
- if (mode === 'reset') {
- anyDifficultOptions = true;
- this.optionsManager.reset(options);
- }
- else if (mode === 'dynamic') {
- this.optionsManager.addDynamic(options); // takes higher precedence
- }
- else {
- this.optionsManager.add(options);
- }
+ this.optionsManager.mutate(normalUpdates, removals, isDynamic);
if (anyDifficultOptions) {
- this.handleOptions(this.optionsManager.computed); // only for "difficult" options
- this.needsFullRerender = true;
- this.batchRendering(function () {
+ this.handleOptions(this.optionsManager.computed);
+ }
+ this.batchRendering(function () {
+ if (anyDifficultOptions) {
if (isTimeZoneDirty) {
_this.dispatch({
type: 'CHANGE_TIMEZONE',
@@ -7002,34 +6920,24 @@ Docs & License: https://fullcalendar.io/
});
}
/* HACK
- has the same effect as calling this.requestRerender(true)
+ has the same effect as calling this.requestRerender()
but recomputes the state's dateProfile
*/
_this.dispatch({
type: 'SET_VIEW_TYPE',
viewType: _this.state.viewType
});
- });
- }
- if (isSizeDirty) {
- this.updateSize();
- }
- };
- Calendar.prototype.setOption = function (name, val) {
- var _a;
- this.processOptions((_a = {}, _a[name] = val, _a), 'dynamic');
- };
- 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;
+ }
+ 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
@@ -7084,10 +6992,10 @@ Docs & License: https://fullcalendar.io/
};
Calendar.prototype.releaseAfterSizingTriggers = function () {
var afterSizingTriggers = this.afterSizingTriggers;
- for (var name_7 in afterSizingTriggers) {
- for (var _i = 0, _a = afterSizingTriggers[name_7]; _i < _a.length; _i++) {
+ 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_7, args);
+ this.publiclyTrigger(name_4, args);
}
}
this.afterSizingTriggers = {};
@@ -7102,7 +7010,7 @@ Docs & License: https://fullcalendar.io/
var dateMarker = null;
if (dateOrRange) {
if (dateOrRange.start && dateOrRange.end) { // a range
- this.optionsManager.addDynamic({ visibleRange: dateOrRange }); // will not rerender
+ this.optionsManager.mutate({ visibleRange: dateOrRange }, []); // will not rerender
this.handleOptions(this.optionsManager.computed); // ...but yuck
}
else { // a date
@@ -7142,11 +7050,17 @@ Docs & License: https://fullcalendar.io/
// 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 viewTypes;
+ var component = this.component;
+ var viewTypes = [];
var i;
var spec;
- // put views that have buttons first. there will be duplicates, but oh well
- viewTypes = this.component.header.viewsWithButtons; // TODO: include footer as well?
+ // 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);
}
@@ -7315,9 +7229,7 @@ Docs & License: https://fullcalendar.io/
}
};
Calendar.prototype.triggerDateSelect = function (selection, pev) {
- var arg = this.buildDateSpanApi(selection);
- arg.jsEvent = pev ? pev.origEvent : null;
- arg.view = this.view;
+ var arg = __assign({}, this.buildDateSpanApi(selection), { jsEvent: pev ? pev.origEvent : null, view: this.view });
this.publiclyTrigger('select', [arg]);
};
Calendar.prototype.triggerDateUnselect = function (pev) {
@@ -7330,10 +7242,8 @@ Docs & License: https://fullcalendar.io/
};
// TODO: receive pev?
Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) {
- var arg = this.buildDatePointApi(dateSpan);
- arg.dayEl = dayEl;
- arg.jsEvent = ev;
- arg.view = view;
+ 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) {
@@ -7503,11 +7413,22 @@ Docs & License: https://fullcalendar.io/
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
// -----------------------------------------------------------------------------------------------------------------
+ function buildComponentContext$1(theme, dateEnv, options) {
+ return new ComponentContext(this, theme, dateEnv, options, null);
+ }
function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) {
return new DateEnv({
calendarSystem: 'gregory',
@@ -7549,9 +7470,8 @@ Docs & License: https://fullcalendar.io/
var View = /** @class */ (function (_super) {
__extends(View, _super);
- function View(context, viewSpec, dateProfileGenerator, parentEl) {
- var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK)
- ) || this;
+ function View(viewSpec, parentEl) {
+ var _this = _super.call(this, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' })) || this;
_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]);
@@ -7560,10 +7480,7 @@ Docs & License: https://fullcalendar.io/
_this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]);
_this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]);
_this.viewSpec = viewSpec;
- _this.dateProfileGenerator = dateProfileGenerator;
_this.type = viewSpec.type;
- _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder'));
- _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold'));
parentEl.appendChild(_this.el);
_this.initialize();
return _this;
@@ -7574,35 +7491,35 @@ Docs & License: https://fullcalendar.io/
// Date Setting/Unsetting
// -----------------------------------------------------------------------------------------------------------------
get: function () {
- return this.dateEnv.toDate(this.props.dateProfile.activeRange.start);
+ return this.context.dateEnv.toDate(this.props.dateProfile.activeRange.start);
},
enumerable: true,
configurable: true
});
Object.defineProperty(View.prototype, "activeEnd", {
get: function () {
- return this.dateEnv.toDate(this.props.dateProfile.activeRange.end);
+ return this.context.dateEnv.toDate(this.props.dateProfile.activeRange.end);
},
enumerable: true,
configurable: true
});
Object.defineProperty(View.prototype, "currentStart", {
get: function () {
- return this.dateEnv.toDate(this.props.dateProfile.currentRange.start);
+ return this.context.dateEnv.toDate(this.props.dateProfile.currentRange.start);
},
enumerable: true,
configurable: true
});
Object.defineProperty(View.prototype, "currentEnd", {
get: function () {
- return this.dateEnv.toDate(this.props.dateProfile.currentRange.end);
+ return this.context.dateEnv.toDate(this.props.dateProfile.currentRange.end);
},
enumerable: true,
configurable: true
});
// General Rendering
// -----------------------------------------------------------------------------------------------------------------
- View.prototype.render = function (props) {
+ View.prototype.render = function (props, context) {
this.renderDatesMem(props.dateProfile);
this.renderBusinessHoursMem(props.businessHours);
this.renderDateSelectionMem(props.dateSelection);
@@ -7611,6 +7528,9 @@ Docs & License: https://fullcalendar.io/
this.renderEventDragMem(props.eventDrag);
this.renderEventResizeMem(props.eventResize);
};
+ View.prototype.beforeUpdate = function () {
+ this.addScroll(this.queryScroll());
+ };
View.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderDatesMem.unrender(); // should unrender everything else
@@ -7618,12 +7538,19 @@ Docs & License: https://fullcalendar.io/
// Sizing
// -----------------------------------------------------------------------------------------------------------------
View.prototype.updateSize = function (isResize, viewHeight, isAuto) {
- var calendar = this.calendar;
- if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) {
+ var calendar = this.context.calendar;
+ if (isResize) {
+ this.addScroll(this.queryScroll()); // NOTE: same code as in beforeUpdate
+ }
+ 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);
}
+ // NOTE: popScroll is called by CalendarComponent
};
View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
};
@@ -7631,8 +7558,9 @@ Docs & License: https://fullcalendar.io/
// -----------------------------------------------------------------------------------------------------------------
View.prototype.renderDatesWrap = function (dateProfile) {
this.renderDates(dateProfile);
- this.addScroll({ isDateInit: true });
- this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon
+ this.addScroll({
+ duration: createDuration(this.context.options.scrollTime)
+ });
};
View.prototype.unrenderDatesWrap = function () {
this.stopNowIndicator();
@@ -7665,7 +7593,7 @@ Docs & License: https://fullcalendar.io/
// util for subclasses
View.prototype.sliceEvents = function (eventStore, allDay) {
var props = this.props;
- return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg;
+ return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.context.nextDayThreshold : null).fg;
};
// Event Selection
// -----------------------------------------------------------------------------------------------------------------
@@ -7714,17 +7642,18 @@ Docs & License: https://fullcalendar.io/
// 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
- View.prototype.startNowIndicator = function (dateProfile) {
+ // USAGE: must be called manually from subclasses' render methods! don't need to call stopNowIndicator tho
+ View.prototype.startNowIndicator = function (dateProfile, dateProfileGenerator) {
var _this = this;
- var dateEnv = this.dateEnv;
+ var _a = this.context, calendar = _a.calendar, dateEnv = _a.dateEnv, options = _a.options;
var unit;
var update;
var delay; // ms wait value
- if (this.opt('nowIndicator')) {
- unit = this.getNowIndicatorUnit(dateProfile);
+ if (options.nowIndicator && !this.initialNowDate) {
+ unit = this.getNowIndicatorUnit(dateProfile, dateProfileGenerator);
if (unit) {
update = this.updateNowIndicator.bind(this);
- this.initialNowDate = this.calendar.getNow();
+ this.initialNowDate = calendar.getNow();
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();
@@ -7758,20 +7687,20 @@ Docs & License: https://fullcalendar.io/
// 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 () {
+ if (this.nowIndicatorTimeoutID) {
+ clearTimeout(this.nowIndicatorTimeoutID);
+ this.nowIndicatorTimeoutID = null;
+ }
+ if (this.nowIndicatorIntervalID) {
+ clearInterval(this.nowIndicatorIntervalID);
+ this.nowIndicatorIntervalID = null;
+ }
if (this.isNowIndicatorRendered) {
- if (this.nowIndicatorTimeoutID) {
- clearTimeout(this.nowIndicatorTimeoutID);
- this.nowIndicatorTimeoutID = null;
- }
- if (this.nowIndicatorIntervalID) {
- clearInterval(this.nowIndicatorIntervalID);
- this.nowIndicatorIntervalID = null;
- }
this.unrenderNowIndicator();
this.isNowIndicatorRendered = false;
}
};
- View.prototype.getNowIndicatorUnit = function (dateProfile) {
+ View.prototype.getNowIndicatorUnit = function (dateProfile, dateProfileGenerator) {
// subclasses should implement
};
// Renders a current time indicator at the given datetime
@@ -7784,16 +7713,20 @@ Docs & License: https://fullcalendar.io/
};
/* Scroller
------------------------------------------------------------------------------------------------------------------*/
- View.prototype.addScroll = function (scroll) {
- var queuedScroll = this.queuedScroll || (this.queuedScroll = {});
- __assign(queuedScroll, scroll);
+ View.prototype.addScroll = function (scroll, isForced) {
+ if (isForced) {
+ scroll.isForced = isForced;
+ }
+ __assign(this.queuedScroll || (this.queuedScroll = {}), scroll);
};
View.prototype.popScroll = function (isResize) {
this.applyQueuedScroll(isResize);
this.queuedScroll = null;
};
View.prototype.applyQueuedScroll = function (isResize) {
- this.applyScroll(this.queuedScroll || {}, isResize);
+ if (this.queuedScroll) {
+ this.applyScroll(this.queuedScroll, isResize);
+ }
};
View.prototype.queryScroll = function () {
var scroll = {};
@@ -7803,17 +7736,18 @@ Docs & License: https://fullcalendar.io/
return scroll;
};
View.prototype.applyScroll = function (scroll, isResize) {
- if (scroll.isDateInit) {
- delete scroll.isDateInit;
+ var duration = scroll.duration, isForced = scroll.isForced;
+ if (duration != null && !isForced) {
+ delete scroll.duration;
if (this.props.dateProfile) { // dates rendered yet?
- __assign(scroll, this.computeInitialDateScroll());
+ __assign(scroll, this.computeDateScroll(duration));
}
}
if (this.props.dateProfile) { // dates rendered yet?
this.applyDateScroll(scroll);
}
};
- View.prototype.computeInitialDateScroll = function () {
+ View.prototype.computeDateScroll = function (duration) {
return {}; // subclasses must implement
};
View.prototype.queryDateScroll = function () {
@@ -7822,6 +7756,10 @@ Docs & License: https://fullcalendar.io/
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);
@@ -7829,12 +7767,12 @@ Docs & License: https://fullcalendar.io/
View.prototype.dateProfileGeneratorClass = DateProfileGenerator;
var FgEventRenderer = /** @class */ (function () {
- function FgEventRenderer(context) {
+ function FgEventRenderer() {
this.segs = [];
this.isSizeDirty = false;
- this.context = context;
}
- FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) {
+ FgEventRenderer.prototype.renderSegs = function (context, segs, mirrorInfo) {
+ this.context = context;
this.rangeUpdated(); // called too frequently :(
// render an `.el` on each seg
// returns a subset of the segs. segs that were actually rendered
@@ -7842,10 +7780,10 @@ Docs & License: https://fullcalendar.io/
this.segs = segs;
this.attachSegs(segs, mirrorInfo);
this.isSizeDirty = true;
- this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo));
+ triggerRenderedSegs(this.context, this.segs, Boolean(mirrorInfo));
};
- FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) {
- this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo));
+ FgEventRenderer.prototype.unrender = function (context, _segs, mirrorInfo) {
+ triggerWillRemoveSegs(this.context, this.segs, Boolean(mirrorInfo));
this.detachSegs(this.segs);
this.segs = [];
};
@@ -7884,7 +7822,7 @@ Docs & License: https://fullcalendar.io/
seg.el = el;
}
});
- segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo));
+ segs = filterSegsViaEls(this.context, segs, Boolean(mirrorInfo));
}
return segs;
};
@@ -7966,7 +7904,7 @@ Docs & License: https://fullcalendar.io/
};
};
FgEventRenderer.prototype.sortEventSegs = function (segs) {
- var specs = this.context.view.eventOrderSpecs;
+ var specs = this.context.eventOrderSpecs;
var objs = segs.map(buildSegCompareObj);
objs.sort(function (obj0, obj1) {
return compareByFieldSpecs(obj0, obj1, specs);
@@ -8047,19 +7985,22 @@ Docs & License: https://fullcalendar.io/
});
}
+ /*
+ TODO: when refactoring this class, make a new FillRenderer instance for each `type`
+ */
var FillRenderer = /** @class */ (function () {
- function FillRenderer(context) {
+ function FillRenderer() {
this.fillSegTag = 'div';
this.dirtySizeFlags = {};
- this.context = context;
this.containerElsByType = {};
this.segsByType = {};
}
FillRenderer.prototype.getSegsByType = function (type) {
return this.segsByType[type] || [];
};
- FillRenderer.prototype.renderSegs = function (type, segs) {
+ FillRenderer.prototype.renderSegs = function (type, context, segs) {
var _a;
+ this.context = context;
var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs
var containerEls = this.attachSegs(type, renderedSegs);
if (containerEls) {
@@ -8067,16 +8008,16 @@ Docs & License: https://fullcalendar.io/
}
this.segsByType[type] = renderedSegs;
if (type === 'bgEvent') {
- this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false
+ triggerRenderedSegs(context, renderedSegs, false); // isMirror=false
}
this.dirtySizeFlags[type] = true;
};
// Unrenders a specific type of fill that is currently rendered on the grid
- FillRenderer.prototype.unrender = function (type) {
+ FillRenderer.prototype.unrender = function (type, context) {
var segs = this.segsByType[type];
if (segs) {
if (type === 'bgEvent') {
- this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false
+ triggerWillRemoveSegs(context, segs, false); // isMirror=false
}
this.detachSegs(type, segs);
}
@@ -8101,7 +8042,7 @@ Docs & License: https://fullcalendar.io/
}
});
if (type === 'bgEvent') {
- segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements
+ segs = filterSegsViaEls(this.context, segs, false // isMirror. background events can never be mirror elements
);
}
// correct element type? (would be bad if a non-TD were inserted into a table for example)
@@ -8267,7 +8208,7 @@ Docs & License: https://fullcalendar.io/
}
}
function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) {
- var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options;
+ var dateEnv = context.dateEnv, theme = context.theme, options = context.options;
var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow.
var classNames = [
'fc-day-header',
@@ -8307,7 +8248,7 @@ Docs & License: https://fullcalendar.io/
'>' +
(isDateValid ?
// don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
- buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
+ buildGotoAnchorHtml(options, dateEnv, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
// if not valid, display text, but no link
innerHtml) +
'</th>';
@@ -8315,37 +8256,48 @@ Docs & License: https://fullcalendar.io/
var DayHeader = /** @class */ (function (_super) {
__extends(DayHeader, _super);
- function DayHeader(context, parentEl) {
- var _this = _super.call(this, context) || this;
- parentEl.innerHTML = ''; // because might be nbsp
- parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' +
- '<table class="' + _this.theme.getClass('tableGrid') + '">' +
- '<thead></thead>' +
- '</table>' +
- '</div>'));
- _this.thead = _this.el.querySelector('thead');
+ function DayHeader(parentEl) {
+ var _this = _super.call(this) || this;
+ _this.renderSkeleton = memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
+ _this.parentEl = parentEl;
return _this;
}
- DayHeader.prototype.destroy = function () {
- removeElement(this.el);
- };
- DayHeader.prototype.render = function (props) {
+ DayHeader.prototype.render = function (props, context) {
var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays;
var parts = [];
+ this.renderSkeleton(context);
if (props.renderIntroHtml) {
parts.push(props.renderIntroHtml());
}
- var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') ||
+ var colHeadFormat = createFormatter(context.options.columnHeaderFormat ||
computeFallbackHeaderFormat(datesRepDistinctDays, dates.length));
for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) {
var date = dates_1[_i];
- parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context));
+ parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, context));
}
- if (this.isRtl) {
+ if (context.isRtl) {
parts.reverse();
}
this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>';
};
+ 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);
+ };
return DayHeader;
}(Component));
@@ -8494,16 +8446,16 @@ Docs & License: https://fullcalendar.io/
this.sliceEventDrag = memoize(this._sliceInteraction);
this.sliceEventResize = memoize(this._sliceInteraction);
}
- Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) {
+ Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, calendar, component) {
var extraArgs = [];
- for (var _i = 4; _i < arguments.length; _i++) {
- extraArgs[_i - 4] = arguments[_i];
+ for (var _i = 5; _i < arguments.length; _i++) {
+ extraArgs[_i - 5] = arguments[_i];
}
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)),
- businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)),
+ businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, calendar, component].concat(extraArgs)),
fgEventSegs: eventSegs.fg,
bgEventSegs: eventSegs.bg,
eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)),
@@ -8521,15 +8473,15 @@ Docs & License: https://fullcalendar.io/
{},
component].concat(extraArgs));
};
- Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) {
+ Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, calendar, component) {
var extraArgs = [];
- for (var _i = 4; _i < arguments.length; _i++) {
- extraArgs[_i - 4] = arguments[_i];
+ for (var _i = 5; _i < arguments.length; _i++) {
+ extraArgs[_i - 5] = arguments[_i];
}
if (!businessHours) {
return [];
}
- return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar),
+ return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), calendar),
{},
dateProfile,
nextDayThreshold,
@@ -8575,7 +8527,7 @@ Docs & License: https://fullcalendar.io/
if (!dateSpan) {
return [];
}
- var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar);
+ var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.context.calendar);
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];
@@ -8631,10 +8583,11 @@ Docs & License: https://fullcalendar.io/
// exports
// --------------------------------------------------------------------------------------------------
- var version = '4.0.2';
+ var version = '4.4.2';
exports.Calendar = Calendar;
exports.Component = Component;
+ exports.ComponentContext = ComponentContext;
exports.DateComponent = DateComponent;
exports.DateEnv = DateEnv;
exports.DateProfileGenerator = DateProfileGenerator;
@@ -8682,6 +8635,9 @@ Docs & License: https://fullcalendar.io/
exports.compensateScroll = compensateScroll;
exports.computeClippingRect = computeClippingRect;
exports.computeEdges = computeEdges;
+ exports.computeEventDraggable = computeEventDraggable;
+ exports.computeEventEndResizable = computeEventEndResizable;
+ exports.computeEventStartResizable = computeEventStartResizable;
exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat;
exports.computeHeightAndMargins = computeHeightAndMargins;
exports.computeInnerRect = computeInnerRect;
@@ -8719,7 +8675,6 @@ Docs & License: https://fullcalendar.io/
exports.formatDate = formatDate;
exports.formatIsoTimeString = formatIsoTimeString;
exports.formatRange = formatRange;
- exports.freezeRaw = freezeRaw;
exports.getAllDayHtml = getAllDayHtml;
exports.getClippingParents = getClippingParents;
exports.getDayClasses = getDayClasses;
@@ -8741,11 +8696,10 @@ Docs & License: https://fullcalendar.io/
exports.isInt = isInt;
exports.isInteractionValid = isInteractionValid;
exports.isMultiDayRange = isMultiDayRange;
- exports.isObjectsSimilar = isObjectsSimilar;
+ exports.isPropsEqual = isPropsEqual;
exports.isPropsValid = isPropsValid;
exports.isSingleDay = isSingleDay;
exports.isValidDate = isValidDate;
- exports.isValuesSimilar = isValuesSimilar;
exports.listenBySelector = listenBySelector;
exports.mapHash = mapHash;
exports.matchCellWidths = matchCellWidths;