elements work best with integers. round up to ensure contents fits
+ }
+ function getSectionHasLiquidHeight(props, sectionConfig) {
+ return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
+ }
+ function getAllowYScrolling(props, sectionConfig) {
+ return (
+ sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
+ getSectionHasLiquidHeight(props, sectionConfig)
+ ); // if the section is liquid height, it might condense enough to require scrollbars
+ }
+ // TODO: ONLY use `arg`. force out internal function to use same API
+ function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
+ var expandRows = arg.expandRows;
+ var content =
+ typeof chunkConfig.content === "function"
+ ? chunkConfig.content(arg)
+ : createElement(
+ "table",
+ {
+ role: "presentation",
+ className: [
+ chunkConfig.tableClassName,
+ sectionConfig.syncRowHeights ? "fc-scrollgrid-sync-table" : ""
+ ].join(" "),
+ style: {
+ minWidth: arg.tableMinWidth,
+ width: arg.clientWidth,
+ height: expandRows ? arg.clientHeight : "" // css `height` on a
serves as a min-height
+ }
+ },
+ arg.tableColGroupNode,
+ createElement(
+ isHeader ? "thead" : "tbody",
+ {
+ role: "presentation"
+ },
+ typeof chunkConfig.rowContent === "function"
+ ? chunkConfig.rowContent(arg)
+ : chunkConfig.rowContent
+ )
+ );
+ return content;
+ }
+ function isColPropsEqual(cols0, cols1) {
+ return isArraysEqual(cols0, cols1, isPropsEqual);
+ }
+ function renderMicroColGroup(cols, shrinkWidth) {
+ var colNodes = [];
+ /*
+ for ColProps with spans, it would have been great to make a single
+ HOWEVER, Chrome was getting messing up distributing the width to
/
elements with colspans.
+ SOLUTION: making individual
elements makes Chrome behave.
+ */
+ for (var _i = 0, cols_1 = cols; _i < cols_1.length; _i++) {
+ var colProps = cols_1[_i];
+ var span = colProps.span || 1;
+ for (var i = 0; i < span; i += 1) {
+ colNodes.push(
+ createElement("col", {
+ style: {
+ width:
+ colProps.width === "shrink"
+ ? sanitizeShrinkWidth(shrinkWidth)
+ : colProps.width || "",
+ minWidth: colProps.minWidth || ""
+ }
+ })
+ );
+ }
+ }
+ return createElement.apply(
+ void 0,
+ __spreadArray(["colgroup", {}], colNodes)
+ );
+ }
+ function sanitizeShrinkWidth(shrinkWidth) {
+ /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
+ 4 accounts for 2 2-pixel borders. TODO: better solution? */
+ return shrinkWidth == null ? 4 : shrinkWidth;
+ }
+ function hasShrinkWidth(cols) {
+ for (var _i = 0, cols_2 = cols; _i < cols_2.length; _i++) {
+ var col = cols_2[_i];
+ if (col.width === "shrink") {
+ return true;
+ }
+ }
+ return false;
+ }
+ function getScrollGridClassNames(liquid, context) {
+ var classNames = ["fc-scrollgrid", context.theme.getClass("table")];
+ if (liquid) {
+ classNames.push("fc-scrollgrid-liquid");
+ }
+ return classNames;
+ }
+ function getSectionClassNames(sectionConfig, wholeTableVGrow) {
+ var classNames = [
+ "fc-scrollgrid-section",
+ "fc-scrollgrid-section-" + sectionConfig.type,
+ sectionConfig.className // used?
+ ];
+ if (
+ wholeTableVGrow &&
+ sectionConfig.liquid &&
+ sectionConfig.maxHeight == null
+ ) {
+ classNames.push("fc-scrollgrid-section-liquid");
+ }
+ if (sectionConfig.isSticky) {
+ classNames.push("fc-scrollgrid-section-sticky");
+ }
+ return classNames;
+ }
+ function renderScrollShim(arg) {
+ return createElement("div", {
+ className: "fc-scrollgrid-sticky-shim",
+ style: {
+ width: arg.clientWidth,
+ minWidth: arg.tableMinWidth
+ }
+ });
+ }
+ function getStickyHeaderDates(options) {
+ var stickyHeaderDates = options.stickyHeaderDates;
+ if (stickyHeaderDates == null || stickyHeaderDates === "auto") {
+ stickyHeaderDates =
+ options.height === "auto" || options.viewHeight === "auto";
+ }
+ return stickyHeaderDates;
+ }
+ function getStickyFooterScrollbar(options) {
+ var stickyFooterScrollbar = options.stickyFooterScrollbar;
+ if (stickyFooterScrollbar == null || stickyFooterScrollbar === "auto") {
+ stickyFooterScrollbar =
+ options.height === "auto" || options.viewHeight === "auto";
+ }
+ return stickyFooterScrollbar;
+ }
+
+ var SimpleScrollGrid = /** @class */ (function(_super) {
+ __extends(SimpleScrollGrid, _super);
+ function SimpleScrollGrid() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.processCols = memoize(function(a) {
+ return a;
+ }, isColPropsEqual); // so we get same `cols` props every time
+ // yucky to memoize VNodes, but much more efficient for consumers
+ _this.renderMicroColGroup = memoize(renderMicroColGroup);
+ _this.scrollerRefs = new RefMap();
+ _this.scrollerElRefs = new RefMap(_this._handleScrollerEl.bind(_this));
+ _this.state = {
+ shrinkWidth: null,
+ forceYScrollbars: false,
+ scrollerClientWidths: {},
+ scrollerClientHeights: {}
+ };
+ // TODO: can do a really simple print-view. dont need to join rows
+ _this.handleSizing = function() {
+ _this.setState(
+ __assign(
+ { shrinkWidth: _this.computeShrinkWidth() },
+ _this.computeScrollerDims()
+ )
+ );
+ };
+ return _this;
+ }
+ SimpleScrollGrid.prototype.render = function() {
+ var _a = this,
+ props = _a.props,
+ state = _a.state,
+ context = _a.context;
+ var sectionConfigs = props.sections || [];
+ var cols = this.processCols(props.cols);
+ var microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
+ var classNames = getScrollGridClassNames(props.liquid, context);
+ if (props.collapsibleWidth) {
+ classNames.push("fc-scrollgrid-collapsible");
+ }
+ // TODO: make DRY
+ var configCnt = sectionConfigs.length;
+ var configI = 0;
+ var currentConfig;
+ var headSectionNodes = [];
+ var bodySectionNodes = [];
+ var footSectionNodes = [];
+ while (
+ configI < configCnt &&
+ (currentConfig = sectionConfigs[configI]).type === "header"
+ ) {
+ headSectionNodes.push(
+ this.renderSection(currentConfig, microColGroupNode, true)
+ );
+ configI += 1;
+ }
+ while (
+ configI < configCnt &&
+ (currentConfig = sectionConfigs[configI]).type === "body"
+ ) {
+ bodySectionNodes.push(
+ this.renderSection(currentConfig, microColGroupNode, false)
+ );
+ configI += 1;
+ }
+ while (
+ configI < configCnt &&
+ (currentConfig = sectionConfigs[configI]).type === "footer"
+ ) {
+ footSectionNodes.push(
+ this.renderSection(currentConfig, microColGroupNode, true)
+ );
+ configI += 1;
+ }
+ // firefox bug: when setting height on table and there is a thead or tfoot,
+ // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
+ // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
+ // if so, use a simpler dom structure, jam everything into a lone tbody.
+ var isBuggy = !getCanVGrowWithinCell();
+ var roleAttrs = { role: "rowgroup" };
+ return createElement(
+ "table",
+ {
+ role: "grid",
+ className: classNames.join(" "),
+ style: { height: props.height }
+ },
+ Boolean(!isBuggy && headSectionNodes.length) &&
+ createElement.apply(
+ void 0,
+ __spreadArray(["thead", roleAttrs], headSectionNodes)
+ ),
+ Boolean(!isBuggy && bodySectionNodes.length) &&
+ createElement.apply(
+ void 0,
+ __spreadArray(["tbody", roleAttrs], bodySectionNodes)
+ ),
+ Boolean(!isBuggy && footSectionNodes.length) &&
+ createElement.apply(
+ void 0,
+ __spreadArray(["tfoot", roleAttrs], footSectionNodes)
+ ),
+ isBuggy &&
+ createElement.apply(
+ void 0,
+ __spreadArray(
+ __spreadArray(
+ __spreadArray(["tbody", roleAttrs], headSectionNodes),
+ bodySectionNodes
+ ),
+ footSectionNodes
+ )
+ )
+ );
+ };
+ SimpleScrollGrid.prototype.renderSection = function(
+ sectionConfig,
+ microColGroupNode,
+ isHeader
+ ) {
+ if ("outerContent" in sectionConfig) {
+ return createElement(
+ Fragment,
+ { key: sectionConfig.key },
+ sectionConfig.outerContent
+ );
+ }
+ return createElement(
+ "tr",
+ {
+ key: sectionConfig.key,
+ role: "presentation",
+ className: getSectionClassNames(
+ sectionConfig,
+ this.props.liquid
+ ).join(" ")
+ },
+ this.renderChunkTd(
+ sectionConfig,
+ microColGroupNode,
+ sectionConfig.chunk,
+ isHeader
+ )
+ );
+ };
+ SimpleScrollGrid.prototype.renderChunkTd = function(
+ sectionConfig,
+ microColGroupNode,
+ chunkConfig,
+ isHeader
+ ) {
+ if ("outerContent" in chunkConfig) {
+ return chunkConfig.outerContent;
+ }
+ var props = this.props;
+ var _a = this.state,
+ forceYScrollbars = _a.forceYScrollbars,
+ scrollerClientWidths = _a.scrollerClientWidths,
+ scrollerClientHeights = _a.scrollerClientHeights;
+ var needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
+ var isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
+ // for `!props.liquid` - is WHOLE scrollgrid natural height?
+ // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
+ var overflowY = !props.liquid
+ ? "visible"
+ : forceYScrollbars
+ ? "scroll"
+ : !needsYScrolling
+ ? "hidden"
+ : "auto";
+ var sectionKey = sectionConfig.key;
+ var content = renderChunkContent(
+ sectionConfig,
+ chunkConfig,
+ {
+ tableColGroupNode: microColGroupNode,
+ tableMinWidth: "",
+ clientWidth:
+ !props.collapsibleWidth &&
+ scrollerClientWidths[sectionKey] !== undefined
+ ? scrollerClientWidths[sectionKey]
+ : null,
+ clientHeight:
+ scrollerClientHeights[sectionKey] !== undefined
+ ? scrollerClientHeights[sectionKey]
+ : null,
+ expandRows: sectionConfig.expandRows,
+ syncRowHeights: false,
+ rowSyncHeights: [],
+ reportRowHeightChange: function() {}
+ },
+ isHeader
+ );
+ return createElement(
+ isHeader ? "th" : "td",
+ {
+ ref: chunkConfig.elRef,
+ role: "presentation"
+ },
+ createElement(
+ "div",
+ {
+ className:
+ "fc-scroller-harness" +
+ (isLiquid ? " fc-scroller-harness-liquid" : "")
+ },
+ createElement(
+ Scroller,
+ {
+ ref: this.scrollerRefs.createRef(sectionKey),
+ elRef: this.scrollerElRefs.createRef(sectionKey),
+ overflowY: overflowY,
+ overflowX: !props.liquid
+ ? "visible"
+ : "hidden" /* natural height? */,
+ maxHeight: sectionConfig.maxHeight,
+ liquid: isLiquid,
+ // because its within a harness
+ liquidIsAbsolute: true
+ },
+ content
+ )
+ )
+ );
+ };
+ SimpleScrollGrid.prototype._handleScrollerEl = function(scrollerEl, key) {
+ var section = getSectionByKey(this.props.sections, key);
+ if (section) {
+ setRef(section.chunk.scrollerElRef, scrollerEl);
+ }
+ };
+ SimpleScrollGrid.prototype.componentDidMount = function() {
+ this.handleSizing();
+ this.context.addResizeHandler(this.handleSizing);
+ };
+ SimpleScrollGrid.prototype.componentDidUpdate = function() {
+ // TODO: need better solution when state contains non-sizing things
+ this.handleSizing();
+ };
+ SimpleScrollGrid.prototype.componentWillUnmount = function() {
+ this.context.removeResizeHandler(this.handleSizing);
+ };
+ SimpleScrollGrid.prototype.computeShrinkWidth = function() {
+ return hasShrinkWidth(this.props.cols)
+ ? computeShrinkWidth(this.scrollerElRefs.getAll())
+ : 0;
+ };
+ SimpleScrollGrid.prototype.computeScrollerDims = function() {
+ var scrollbarWidth = getScrollbarWidths();
+ var _a = this,
+ scrollerRefs = _a.scrollerRefs,
+ scrollerElRefs = _a.scrollerElRefs;
+ var forceYScrollbars = false;
+ var scrollerClientWidths = {};
+ var scrollerClientHeights = {};
+ for (var sectionKey in scrollerRefs.currentMap) {
+ var scroller = scrollerRefs.currentMap[sectionKey];
+ if (scroller && scroller.needsYScrolling()) {
+ forceYScrollbars = true;
+ break;
+ }
+ }
+ for (var _i = 0, _b = this.props.sections; _i < _b.length; _i++) {
+ var section = _b[_i];
+ var sectionKey = section.key;
+ var scrollerEl = scrollerElRefs.currentMap[sectionKey];
+ if (scrollerEl) {
+ var harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
+ scrollerClientWidths[sectionKey] = Math.floor(
+ harnessEl.getBoundingClientRect().width -
+ (forceYScrollbars
+ ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
+ : 0)
+ );
+ scrollerClientHeights[sectionKey] = Math.floor(
+ harnessEl.getBoundingClientRect().height
+ );
+ }
+ }
+ return {
+ forceYScrollbars: forceYScrollbars,
+ scrollerClientWidths: scrollerClientWidths,
+ scrollerClientHeights: scrollerClientHeights
+ };
+ };
+ return SimpleScrollGrid;
+ })(BaseComponent);
+ SimpleScrollGrid.addStateEquality({
+ scrollerClientWidths: isPropsEqual,
+ scrollerClientHeights: isPropsEqual
+ });
+ function getSectionByKey(sections, key) {
+ for (var _i = 0, sections_1 = sections; _i < sections_1.length; _i++) {
+ var section = sections_1[_i];
+ if (section.key === key) {
+ return section;
+ }
+ }
+ return null;
+ }
+
+ var EventRoot = /** @class */ (function(_super) {
+ __extends(EventRoot, _super);
+ function EventRoot() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.elRef = createRef();
+ return _this;
+ }
+ EventRoot.prototype.render = function() {
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var options = context.options;
+ var seg = props.seg;
+ var eventRange = seg.eventRange;
+ var ui = eventRange.ui;
+ var hookProps = {
+ event: new EventApi(context, eventRange.def, eventRange.instance),
+ view: context.viewApi,
+ timeText: props.timeText,
+ textColor: ui.textColor,
+ backgroundColor: ui.backgroundColor,
+ borderColor: ui.borderColor,
+ isDraggable:
+ !props.disableDragging && computeSegDraggable(seg, context),
+ isStartResizable:
+ !props.disableResizing && computeSegStartResizable(seg, context),
+ isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
+ isMirror: Boolean(
+ props.isDragging || props.isResizing || props.isDateSelecting
+ ),
+ isStart: Boolean(seg.isStart),
+ isEnd: Boolean(seg.isEnd),
+ isPast: Boolean(props.isPast),
+ isFuture: Boolean(props.isFuture),
+ isToday: Boolean(props.isToday),
+ isSelected: Boolean(props.isSelected),
+ isDragging: Boolean(props.isDragging),
+ isResizing: Boolean(props.isResizing)
+ };
+ var standardClassNames = getEventClassNames(hookProps).concat(
+ ui.classNames
+ );
+ return createElement(
+ RenderHook,
+ {
+ hookProps: hookProps,
+ classNames: options.eventClassNames,
+ content: options.eventContent,
+ defaultContent: props.defaultContent,
+ didMount: options.eventDidMount,
+ willUnmount: options.eventWillUnmount,
+ elRef: this.elRef
+ },
+ function(rootElRef, customClassNames, innerElRef, innerContent) {
+ return props.children(
+ rootElRef,
+ standardClassNames.concat(customClassNames),
+ innerElRef,
+ innerContent,
+ hookProps
+ );
+ }
+ );
+ };
+ EventRoot.prototype.componentDidMount = function() {
+ setElSeg(this.elRef.current, this.props.seg);
+ };
+ /*
+ need to re-assign seg to the element if seg changes, even if the element is the same
+ */
+ EventRoot.prototype.componentDidUpdate = function(prevProps) {
+ var seg = this.props.seg;
+ if (seg !== prevProps.seg) {
+ setElSeg(this.elRef.current, seg);
+ }
+ };
+ return EventRoot;
+ })(BaseComponent);
+
+ // should not be a purecomponent
+ var StandardEvent = /** @class */ (function(_super) {
+ __extends(StandardEvent, _super);
+ function StandardEvent() {
+ return (_super !== null && _super.apply(this, arguments)) || this;
+ }
+ StandardEvent.prototype.render = function() {
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var seg = props.seg;
+ var timeFormat =
+ context.options.eventTimeFormat || props.defaultTimeFormat;
+ var timeText = buildSegTimeText(
+ seg,
+ timeFormat,
+ context,
+ props.defaultDisplayEventTime,
+ props.defaultDisplayEventEnd
+ );
+ return createElement(
+ EventRoot,
+ {
+ seg: seg,
+ timeText: timeText,
+ disableDragging: props.disableDragging,
+ disableResizing: props.disableResizing,
+ defaultContent: props.defaultContent || renderInnerContent$4,
+ isDragging: props.isDragging,
+ isResizing: props.isResizing,
+ isDateSelecting: props.isDateSelecting,
+ isSelected: props.isSelected,
+ isPast: props.isPast,
+ isFuture: props.isFuture,
+ isToday: props.isToday
+ },
+ function(rootElRef, classNames, innerElRef, innerContent, hookProps) {
+ return createElement(
+ "a",
+ __assign(
+ {
+ className: props.extraClassNames.concat(classNames).join(" "),
+ style: {
+ borderColor: hookProps.borderColor,
+ backgroundColor: hookProps.backgroundColor
+ },
+ ref: rootElRef
+ },
+ getSegAnchorAttrs(seg, context)
+ ),
+ createElement(
+ "div",
+ {
+ className: "fc-event-main",
+ ref: innerElRef,
+ style: { color: hookProps.textColor }
+ },
+ innerContent
+ ),
+ hookProps.isStartResizable &&
+ createElement("div", {
+ className: "fc-event-resizer fc-event-resizer-start"
+ }),
+ hookProps.isEndResizable &&
+ createElement("div", {
+ className: "fc-event-resizer fc-event-resizer-end"
+ })
+ );
+ }
+ );
+ };
+ return StandardEvent;
+ })(BaseComponent);
+ function renderInnerContent$4(innerProps) {
+ return createElement(
+ "div",
+ { className: "fc-event-main-frame" },
+ innerProps.timeText &&
+ createElement(
+ "div",
+ { className: "fc-event-time" },
+ innerProps.timeText
+ ),
+ createElement(
+ "div",
+ { className: "fc-event-title-container" },
+ createElement(
+ "div",
+ { className: "fc-event-title fc-sticky" },
+ innerProps.event.title || createElement(Fragment, null, "\u00A0")
+ )
+ )
+ );
+ }
+
+ var NowIndicatorRoot = function(props) {
+ return createElement(ViewContextType.Consumer, null, function(context) {
+ var options = context.options;
+ var hookProps = {
+ isAxis: props.isAxis,
+ date: context.dateEnv.toDate(props.date),
+ view: context.viewApi
+ };
+ return createElement(
+ RenderHook,
+ {
+ hookProps: hookProps,
+ classNames: options.nowIndicatorClassNames,
+ content: options.nowIndicatorContent,
+ didMount: options.nowIndicatorDidMount,
+ willUnmount: options.nowIndicatorWillUnmount
+ },
+ props.children
+ );
+ });
+ };
+
+ var DAY_NUM_FORMAT = createFormatter({ day: "numeric" });
+ var DayCellContent = /** @class */ (function(_super) {
+ __extends(DayCellContent, _super);
+ function DayCellContent() {
+ return (_super !== null && _super.apply(this, arguments)) || this;
+ }
+ DayCellContent.prototype.render = function() {
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var options = context.options;
+ var hookProps = refineDayCellHookProps({
+ date: props.date,
+ dateProfile: props.dateProfile,
+ todayRange: props.todayRange,
+ showDayNumber: props.showDayNumber,
+ extraProps: props.extraHookProps,
+ viewApi: context.viewApi,
+ dateEnv: context.dateEnv
+ });
+ return createElement(
+ ContentHook,
+ {
+ hookProps: hookProps,
+ content: options.dayCellContent,
+ defaultContent: props.defaultContent
+ },
+ props.children
+ );
+ };
+ return DayCellContent;
+ })(BaseComponent);
+ function refineDayCellHookProps(raw) {
+ var date = raw.date,
+ dateEnv = raw.dateEnv;
+ var dayMeta = getDateMeta(date, raw.todayRange, null, raw.dateProfile);
+ return __assign(
+ __assign(
+ __assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta),
+ {
+ dayNumberText: raw.showDayNumber
+ ? dateEnv.format(date, DAY_NUM_FORMAT)
+ : ""
+ }
+ ),
+ raw.extraProps
+ );
+ }
+
+ var DayCellRoot = /** @class */ (function(_super) {
+ __extends(DayCellRoot, _super);
+ function DayCellRoot() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.refineHookProps = memoizeObjArg(refineDayCellHookProps);
+ _this.normalizeClassNames = buildClassNameNormalizer();
+ return _this;
+ }
+ DayCellRoot.prototype.render = function() {
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var options = context.options;
+ var hookProps = this.refineHookProps({
+ date: props.date,
+ dateProfile: props.dateProfile,
+ todayRange: props.todayRange,
+ showDayNumber: props.showDayNumber,
+ extraProps: props.extraHookProps,
+ viewApi: context.viewApi,
+ dateEnv: context.dateEnv
+ });
+ var classNames = getDayClassNames(hookProps, context.theme).concat(
+ hookProps.isDisabled
+ ? [] // don't use custom classNames if disabled
+ : this.normalizeClassNames(options.dayCellClassNames, hookProps)
+ );
+ var dataAttrs = hookProps.isDisabled
+ ? {}
+ : {
+ "data-date": formatDayString(props.date)
+ };
+ return createElement(
+ MountHook,
+ {
+ hookProps: hookProps,
+ didMount: options.dayCellDidMount,
+ willUnmount: options.dayCellWillUnmount,
+ elRef: props.elRef
+ },
+ function(rootElRef) {
+ return props.children(
+ rootElRef,
+ classNames,
+ dataAttrs,
+ hookProps.isDisabled
+ );
+ }
+ );
+ };
+ return DayCellRoot;
+ })(BaseComponent);
+
+ function renderFill(fillType) {
+ return createElement("div", { className: "fc-" + fillType });
+ }
+ var BgEvent = function(props) {
+ return createElement(
+ EventRoot,
+ {
+ defaultContent: renderInnerContent$3,
+ seg: props.seg /* uselesss i think */,
+ timeText: "",
+ disableDragging: true,
+ disableResizing: true,
+ isDragging: false,
+ isResizing: false,
+ isDateSelecting: false,
+ isSelected: false,
+ isPast: props.isPast,
+ isFuture: props.isFuture,
+ isToday: props.isToday
+ },
+ function(rootElRef, classNames, innerElRef, innerContent, hookProps) {
+ return createElement(
+ "div",
+ {
+ ref: rootElRef,
+ className: ["fc-bg-event"].concat(classNames).join(" "),
+ style: {
+ backgroundColor: hookProps.backgroundColor
+ }
+ },
+ innerContent
+ );
+ }
+ );
+ };
+ function renderInnerContent$3(props) {
+ var title = props.event.title;
+ return (
+ title &&
+ createElement("div", { className: "fc-event-title" }, props.event.title)
+ );
+ }
+
+ var WeekNumberRoot = function(props) {
+ return createElement(ViewContextType.Consumer, null, function(context) {
+ var dateEnv = context.dateEnv,
+ options = context.options;
+ var date = props.date;
+ var format = options.weekNumberFormat || props.defaultFormat;
+ var num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
+ var text = dateEnv.format(date, format);
+ var hookProps = { num: num, text: text, date: date };
+ return createElement(
+ RenderHook,
+ {
+ hookProps: hookProps,
+ classNames: options.weekNumberClassNames,
+ content: options.weekNumberContent,
+ defaultContent: renderInner,
+ didMount: options.weekNumberDidMount,
+ willUnmount: options.weekNumberWillUnmount
+ },
+ props.children
+ );
+ });
+ };
+ function renderInner(innerProps) {
+ return innerProps.text;
+ }
+
+ var PADDING_FROM_VIEWPORT = 10;
+ var Popover = /** @class */ (function(_super) {
+ __extends(Popover, _super);
+ function Popover() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.state = {
+ titleId: getUniqueDomId()
+ };
+ _this.handleRootEl = function(el) {
+ _this.rootEl = el;
+ if (_this.props.elRef) {
+ setRef(_this.props.elRef, el);
+ }
+ };
+ // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
+ _this.handleDocumentMouseDown = function(ev) {
+ // only hide the popover if the click happened outside the popover
+ var target = getEventTargetViaRoot(ev);
+ if (!_this.rootEl.contains(target)) {
+ _this.handleCloseClick();
+ }
+ };
+ _this.handleDocumentKeyDown = function(ev) {
+ if (ev.key === "Escape") {
+ _this.handleCloseClick();
+ }
+ };
+ _this.handleCloseClick = function() {
+ var onClose = _this.props.onClose;
+ if (onClose) {
+ onClose();
+ }
+ };
+ return _this;
+ }
+ Popover.prototype.render = function() {
+ var _a = this.context,
+ theme = _a.theme,
+ options = _a.options;
+ var _b = this,
+ props = _b.props,
+ state = _b.state;
+ var classNames = ["fc-popover", theme.getClass("popover")].concat(
+ props.extraClassNames || []
+ );
+ return createPortal(
+ createElement(
+ "div",
+ __assign(
+ {
+ id: props.id,
+ className: classNames.join(" "),
+ "aria-labelledby": state.titleId
+ },
+ props.extraAttrs,
+ { ref: this.handleRootEl }
+ ),
+ createElement(
+ "div",
+ {
+ className: "fc-popover-header " + theme.getClass("popoverHeader")
+ },
+ createElement(
+ "span",
+ { className: "fc-popover-title", id: state.titleId },
+ props.title
+ ),
+ createElement("span", {
+ className: "fc-popover-close " + theme.getIconClass("close"),
+ title: options.closeHint,
+ onClick: this.handleCloseClick
+ })
+ ),
+ createElement(
+ "div",
+ {
+ className: "fc-popover-body " + theme.getClass("popoverContent")
+ },
+ props.children
+ )
+ ),
+ props.parentEl
+ );
+ };
+ Popover.prototype.componentDidMount = function() {
+ document.addEventListener("mousedown", this.handleDocumentMouseDown);
+ document.addEventListener("keydown", this.handleDocumentKeyDown);
+ this.updateSize();
+ };
+ Popover.prototype.componentWillUnmount = function() {
+ document.removeEventListener("mousedown", this.handleDocumentMouseDown);
+ document.removeEventListener("keydown", this.handleDocumentKeyDown);
+ };
+ Popover.prototype.updateSize = function() {
+ var isRtl = this.context.isRtl;
+ var _a = this.props,
+ alignmentEl = _a.alignmentEl,
+ alignGridTop = _a.alignGridTop;
+ var rootEl = this.rootEl;
+ var alignmentRect = computeClippedClientRect(alignmentEl);
+ if (alignmentRect) {
+ var popoverDims = rootEl.getBoundingClientRect();
+ // position relative to viewport
+ var popoverTop = alignGridTop
+ ? elementClosest(
+ alignmentEl,
+ ".fc-scrollgrid"
+ ).getBoundingClientRect().top
+ : alignmentRect.top;
+ var popoverLeft = isRtl
+ ? alignmentRect.right - popoverDims.width
+ : alignmentRect.left;
+ // constrain
+ popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
+ popoverLeft = Math.min(
+ popoverLeft,
+ document.documentElement.clientWidth -
+ PADDING_FROM_VIEWPORT -
+ popoverDims.width
+ );
+ popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
+ var origin_1 = rootEl.offsetParent.getBoundingClientRect();
+ applyStyle(rootEl, {
+ top: popoverTop - origin_1.top,
+ left: popoverLeft - origin_1.left
+ });
+ }
+ };
+ return Popover;
+ })(BaseComponent);
+
+ var MorePopover = /** @class */ (function(_super) {
+ __extends(MorePopover, _super);
+ function MorePopover() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.handleRootEl = function(rootEl) {
+ _this.rootEl = rootEl;
+ if (rootEl) {
+ _this.context.registerInteractiveComponent(_this, {
+ el: rootEl,
+ useEventCenter: false
+ });
+ } else {
+ _this.context.unregisterInteractiveComponent(_this);
+ }
+ };
+ return _this;
+ }
+ MorePopover.prototype.render = function() {
+ var _a = this.context,
+ options = _a.options,
+ dateEnv = _a.dateEnv;
+ var props = this.props;
+ var startDate = props.startDate,
+ todayRange = props.todayRange,
+ dateProfile = props.dateProfile;
+ var title = dateEnv.format(startDate, options.dayPopoverFormat);
+ return createElement(
+ DayCellRoot,
+ {
+ date: startDate,
+ dateProfile: dateProfile,
+ todayRange: todayRange,
+ elRef: this.handleRootEl
+ },
+ function(rootElRef, dayClassNames, dataAttrs) {
+ return createElement(
+ Popover,
+ {
+ elRef: rootElRef,
+ id: props.id,
+ title: title,
+ extraClassNames: ["fc-more-popover"].concat(dayClassNames),
+ extraAttrs: dataAttrs /* TODO: make these time-based when not whole-day? */,
+ parentEl: props.parentEl,
+ alignmentEl: props.alignmentEl,
+ alignGridTop: props.alignGridTop,
+ onClose: props.onClose
+ },
+ createElement(
+ DayCellContent,
+ {
+ date: startDate,
+ dateProfile: dateProfile,
+ todayRange: todayRange
+ },
+ function(innerElRef, innerContent) {
+ return (
+ innerContent &&
+ createElement(
+ "div",
+ { className: "fc-more-popover-misc", ref: innerElRef },
+ innerContent
+ )
+ );
+ }
+ ),
+ props.children
+ );
+ }
+ );
+ };
+ MorePopover.prototype.queryHit = function(
+ positionLeft,
+ positionTop,
+ elWidth,
+ elHeight
+ ) {
+ var _a = this,
+ rootEl = _a.rootEl,
+ props = _a.props;
+ if (
+ positionLeft >= 0 &&
+ positionLeft < elWidth &&
+ positionTop >= 0 &&
+ positionTop < elHeight
+ ) {
+ return {
+ dateProfile: props.dateProfile,
+ dateSpan: __assign(
+ {
+ allDay: true,
+ range: {
+ start: props.startDate,
+ end: props.endDate
+ }
+ },
+ props.extraDateSpan
+ ),
+ dayEl: rootEl,
+ rect: {
+ left: 0,
+ top: 0,
+ right: elWidth,
+ bottom: elHeight
+ },
+ layer: 1 // important when comparing with hits from other components
+ };
+ }
+ return null;
+ };
+ return MorePopover;
+ })(DateComponent);
+
+ var MoreLinkRoot = /** @class */ (function(_super) {
+ __extends(MoreLinkRoot, _super);
+ function MoreLinkRoot() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.linkElRef = createRef();
+ _this.state = {
+ isPopoverOpen: false,
+ popoverId: getUniqueDomId()
+ };
+ _this.handleClick = function(ev) {
+ var _a = _this,
+ props = _a.props,
+ context = _a.context;
+ var moreLinkClick = context.options.moreLinkClick;
+ var date = computeRange(props).start;
+ function buildPublicSeg(seg) {
+ var _a = seg.eventRange,
+ def = _a.def,
+ instance = _a.instance,
+ range = _a.range;
+ return {
+ event: new EventApi(context, def, instance),
+ start: context.dateEnv.toDate(range.start),
+ end: context.dateEnv.toDate(range.end),
+ isStart: seg.isStart,
+ isEnd: seg.isEnd
+ };
+ }
+ if (typeof moreLinkClick === "function") {
+ moreLinkClick = moreLinkClick({
+ date: date,
+ allDay: Boolean(props.allDayDate),
+ allSegs: props.allSegs.map(buildPublicSeg),
+ hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
+ jsEvent: ev,
+ view: context.viewApi
+ });
+ }
+ if (!moreLinkClick || moreLinkClick === "popover") {
+ _this.setState({ isPopoverOpen: true });
+ } else if (typeof moreLinkClick === "string") {
+ // a view name
+ context.calendarApi.zoomTo(date, moreLinkClick);
+ }
+ };
+ _this.handlePopoverClose = function() {
+ _this.setState({ isPopoverOpen: false });
+ };
+ return _this;
+ }
+ MoreLinkRoot.prototype.render = function() {
+ var _this = this;
+ var _a = this,
+ props = _a.props,
+ state = _a.state;
+ return createElement(ViewContextType.Consumer, null, function(context) {
+ var viewApi = context.viewApi,
+ options = context.options,
+ calendarApi = context.calendarApi;
+ var moreLinkText = options.moreLinkText;
+ var moreCnt = props.moreCnt;
+ var range = computeRange(props);
+ var text =
+ typeof moreLinkText === "function" // TODO: eventually use formatWithOrdinals
+ ? moreLinkText.call(calendarApi, moreCnt)
+ : "+" + moreCnt + " " + moreLinkText;
+ var title = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
+ var hookProps = {
+ num: moreCnt,
+ shortText: "+" + moreCnt,
+ text: text,
+ view: viewApi
+ };
+ return createElement(
+ Fragment,
+ null,
+ Boolean(props.moreCnt) &&
+ createElement(
+ RenderHook,
+ {
+ elRef: _this.linkElRef,
+ hookProps: hookProps,
+ classNames: options.moreLinkClassNames,
+ content: options.moreLinkContent,
+ defaultContent: props.defaultContent || renderMoreLinkInner$1,
+ didMount: options.moreLinkDidMount,
+ willUnmount: options.moreLinkWillUnmount
+ },
+ function(rootElRef, customClassNames, innerElRef, innerContent) {
+ return props.children(
+ rootElRef,
+ ["fc-more-link"].concat(customClassNames),
+ innerElRef,
+ innerContent,
+ _this.handleClick,
+ title,
+ state.isPopoverOpen,
+ state.isPopoverOpen ? state.popoverId : ""
+ );
+ }
+ ),
+ state.isPopoverOpen &&
+ createElement(
+ MorePopover,
+ {
+ id: state.popoverId,
+ startDate: range.start,
+ endDate: range.end,
+ dateProfile: props.dateProfile,
+ todayRange: props.todayRange,
+ extraDateSpan: props.extraDateSpan,
+ parentEl: _this.parentEl,
+ alignmentEl: props.alignmentElRef.current,
+ alignGridTop: props.alignGridTop,
+ onClose: _this.handlePopoverClose
+ },
+ props.popoverContent()
+ )
+ );
+ });
+ };
+ MoreLinkRoot.prototype.componentDidMount = function() {
+ this.updateParentEl();
+ };
+ MoreLinkRoot.prototype.componentDidUpdate = function() {
+ this.updateParentEl();
+ };
+ MoreLinkRoot.prototype.updateParentEl = function() {
+ if (this.linkElRef.current) {
+ this.parentEl = elementClosest(
+ this.linkElRef.current,
+ ".fc-view-harness"
+ );
+ }
+ };
+ return MoreLinkRoot;
+ })(BaseComponent);
+ function renderMoreLinkInner$1(props) {
+ return props.text;
+ }
+ function computeRange(props) {
+ if (props.allDayDate) {
+ return {
+ start: props.allDayDate,
+ end: addDays(props.allDayDate, 1)
+ };
+ }
+ var hiddenSegs = props.hiddenSegs;
+ return {
+ start: computeEarliestSegStart(hiddenSegs),
+ end: computeLatestSegEnd(hiddenSegs)
+ };
+ }
+ function computeEarliestSegStart(segs) {
+ return segs.reduce(pickEarliestStart).eventRange.range.start;
+ }
+ function pickEarliestStart(seg0, seg1) {
+ return seg0.eventRange.range.start < seg1.eventRange.range.start
+ ? seg0
+ : seg1;
+ }
+ function computeLatestSegEnd(segs) {
+ return segs.reduce(pickLatestEnd).eventRange.range.end;
+ }
+ function pickLatestEnd(seg0, seg1) {
+ return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
+ }
+
+ // exports
+ // --------------------------------------------------------------------------------------------------
+ var version = "5.10.1"; // important to type it, so .d.ts has generic string
+
+ var Calendar = /** @class */ (function(_super) {
+ __extends(Calendar, _super);
+ function Calendar(el, optionOverrides) {
+ if (optionOverrides === void 0) {
+ optionOverrides = {};
+ }
+ var _this = _super.call(this) || this;
+ _this.isRendering = false;
+ _this.isRendered = false;
+ _this.currentClassNames = [];
+ _this.customContentRenderId = 0; // will affect custom generated classNames?
+ _this.handleAction = function(action) {
+ // actions we know we want to render immediately
+ switch (action.type) {
+ case "SET_EVENT_DRAG":
+ case "SET_EVENT_RESIZE":
+ _this.renderRunner.tryDrain();
+ }
+ };
+ _this.handleData = function(data) {
+ _this.currentData = data;
+ _this.renderRunner.request(data.calendarOptions.rerenderDelay);
+ };
+ _this.handleRenderRequest = function() {
+ if (_this.isRendering) {
+ _this.isRendered = true;
+ var currentData_1 = _this.currentData;
+ render(
+ createElement(
+ CalendarRoot,
+ {
+ options: currentData_1.calendarOptions,
+ theme: currentData_1.theme,
+ emitter: currentData_1.emitter
+ },
+ function(classNames, height, isHeightAuto, forPrint) {
+ _this.setClassNames(classNames);
+ _this.setHeight(height);
+ return createElement(
+ CustomContentRenderContext.Provider,
+ { value: _this.customContentRenderId },
+ createElement(
+ CalendarContent,
+ __assign(
+ { isHeightAuto: isHeightAuto, forPrint: forPrint },
+ currentData_1
+ )
+ )
+ );
+ }
+ ),
+ _this.el
+ );
+ } else if (_this.isRendered) {
+ _this.isRendered = false;
+ unmountComponentAtNode(_this.el);
+ _this.setClassNames([]);
+ _this.setHeight("");
+ }
+ flushToDom();
+ };
+ _this.el = el;
+ _this.renderRunner = new DelayedRunner(_this.handleRenderRequest);
+ new CalendarDataManager({
+ optionOverrides: optionOverrides,
+ calendarApi: _this,
+ onAction: _this.handleAction,
+ onData: _this.handleData
+ });
+ return _this;
+ }
+ Object.defineProperty(Calendar.prototype, "view", {
+ get: function() {
+ return this.currentData.viewApi;
+ }, // for public API
+ enumerable: false,
+ configurable: true
+ });
+ Calendar.prototype.render = function() {
+ var wasRendering = this.isRendering;
+ if (!wasRendering) {
+ this.isRendering = true;
+ } else {
+ this.customContentRenderId += 1;
+ }
+ this.renderRunner.request();
+ if (wasRendering) {
+ this.updateSize();
+ }
+ };
+ Calendar.prototype.destroy = function() {
+ if (this.isRendering) {
+ this.isRendering = false;
+ this.renderRunner.request();
+ }
+ };
+ Calendar.prototype.updateSize = function() {
+ _super.prototype.updateSize.call(this);
+ flushToDom();
+ };
+ Calendar.prototype.batchRendering = function(func) {
+ this.renderRunner.pause("batchRendering");
+ func();
+ this.renderRunner.resume("batchRendering");
+ };
+ Calendar.prototype.pauseRendering = function() {
+ this.renderRunner.pause("pauseRendering");
+ };
+ Calendar.prototype.resumeRendering = function() {
+ this.renderRunner.resume("pauseRendering", true);
+ };
+ Calendar.prototype.resetOptions = function(optionOverrides, append) {
+ this.currentDataManager.resetOptions(optionOverrides, append);
+ };
+ Calendar.prototype.setClassNames = function(classNames) {
+ if (!isArraysEqual(classNames, this.currentClassNames)) {
+ var classList = this.el.classList;
+ for (var _i = 0, _a = this.currentClassNames; _i < _a.length; _i++) {
+ var className = _a[_i];
+ classList.remove(className);
+ }
+ for (
+ var _b = 0, classNames_1 = classNames;
+ _b < classNames_1.length;
+ _b++
+ ) {
+ var className = classNames_1[_b];
+ classList.add(className);
+ }
+ this.currentClassNames = classNames;
+ }
+ };
+ Calendar.prototype.setHeight = function(height) {
+ applyStyleProp(this.el, "height", height);
+ };
+ return Calendar;
+ })(CalendarApi);
+
+ config.touchMouseIgnoreWait = 500;
+ var ignoreMouseDepth = 0;
+ var listenerCnt = 0;
+ var isWindowTouchMoveCancelled = false;
+ /*
+ Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
+ Tracks when the pointer "drags" on a certain element, meaning down+move+up.
+
+ Also, tracks if there was touch-scrolling.
+ Also, can prevent touch-scrolling from happening.
+ Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
+
+ emits:
+ - pointerdown
+ - pointermove
+ - pointerup
+ */
+ var PointerDragging = /** @class */ (function() {
+ function PointerDragging(containerEl) {
+ var _this = this;
+ this.subjectEl = null;
+ // options that can be directly assigned by caller
+ this.selector = ""; // will cause subjectEl in all emitted events to be this element
+ this.handleSelector = "";
+ this.shouldIgnoreMove = false;
+ this.shouldWatchScroll = true; // for simulating pointermove on scroll
+ // internal states
+ this.isDragging = false;
+ this.isTouchDragging = false;
+ this.wasTouchScroll = false;
+ // Mouse
+ // ----------------------------------------------------------------------------------------------------
+ this.handleMouseDown = function(ev) {
+ if (
+ !_this.shouldIgnoreMouse() &&
+ isPrimaryMouseButton(ev) &&
+ _this.tryStart(ev)
+ ) {
+ var pev = _this.createEventFromMouse(ev, true);
+ _this.emitter.trigger("pointerdown", pev);
+ _this.initScrollWatch(pev);
+ if (!_this.shouldIgnoreMove) {
+ document.addEventListener("mousemove", _this.handleMouseMove);
+ }
+ document.addEventListener("mouseup", _this.handleMouseUp);
+ }
+ };
+ this.handleMouseMove = function(ev) {
+ var pev = _this.createEventFromMouse(ev);
+ _this.recordCoords(pev);
+ _this.emitter.trigger("pointermove", pev);
+ };
+ this.handleMouseUp = function(ev) {
+ document.removeEventListener("mousemove", _this.handleMouseMove);
+ document.removeEventListener("mouseup", _this.handleMouseUp);
+ _this.emitter.trigger("pointerup", _this.createEventFromMouse(ev));
+ _this.cleanup(); // call last so that pointerup has access to props
+ };
+ // Touch
+ // ----------------------------------------------------------------------------------------------------
+ this.handleTouchStart = function(ev) {
+ if (_this.tryStart(ev)) {
+ _this.isTouchDragging = true;
+ var pev = _this.createEventFromTouch(ev, true);
+ _this.emitter.trigger("pointerdown", pev);
+ _this.initScrollWatch(pev);
+ // unlike mouse, need to attach to target, not document
+ // https://stackoverflow.com/a/45760014
+ var targetEl = ev.target;
+ if (!_this.shouldIgnoreMove) {
+ targetEl.addEventListener("touchmove", _this.handleTouchMove);
+ }
+ targetEl.addEventListener("touchend", _this.handleTouchEnd);
+ targetEl.addEventListener("touchcancel", _this.handleTouchEnd); // treat it as a touch end
+ // attach a handler to get called when ANY scroll action happens on the page.
+ // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
+ // http://stackoverflow.com/a/32954565/96342
+ window.addEventListener("scroll", _this.handleTouchScroll, true);
+ }
+ };
+ this.handleTouchMove = function(ev) {
+ var pev = _this.createEventFromTouch(ev);
+ _this.recordCoords(pev);
+ _this.emitter.trigger("pointermove", pev);
+ };
+ this.handleTouchEnd = function(ev) {
+ if (_this.isDragging) {
+ // done to guard against touchend followed by touchcancel
+ var targetEl = ev.target;
+ targetEl.removeEventListener("touchmove", _this.handleTouchMove);
+ targetEl.removeEventListener("touchend", _this.handleTouchEnd);
+ targetEl.removeEventListener("touchcancel", _this.handleTouchEnd);
+ window.removeEventListener("scroll", _this.handleTouchScroll, true); // useCaptured=true
+ _this.emitter.trigger("pointerup", _this.createEventFromTouch(ev));
+ _this.cleanup(); // call last so that pointerup has access to props
+ _this.isTouchDragging = false;
+ startIgnoringMouse();
+ }
+ };
+ this.handleTouchScroll = function() {
+ _this.wasTouchScroll = true;
+ };
+ this.handleScroll = function(ev) {
+ if (!_this.shouldIgnoreMove) {
+ var pageX = window.pageXOffset - _this.prevScrollX + _this.prevPageX;
+ var pageY = window.pageYOffset - _this.prevScrollY + _this.prevPageY;
+ _this.emitter.trigger("pointermove", {
+ origEvent: ev,
+ isTouch: _this.isTouchDragging,
+ subjectEl: _this.subjectEl,
+ pageX: pageX,
+ pageY: pageY,
+ deltaX: pageX - _this.origPageX,
+ deltaY: pageY - _this.origPageY
+ });
+ }
+ };
+ this.containerEl = containerEl;
+ this.emitter = new Emitter();
+ containerEl.addEventListener("mousedown", this.handleMouseDown);
+ containerEl.addEventListener("touchstart", this.handleTouchStart, {
+ passive: true
+ });
+ listenerCreated();
+ }
+ PointerDragging.prototype.destroy = function() {
+ this.containerEl.removeEventListener("mousedown", this.handleMouseDown);
+ this.containerEl.removeEventListener(
+ "touchstart",
+ this.handleTouchStart,
+ { passive: true }
+ );
+ listenerDestroyed();
+ };
+ PointerDragging.prototype.tryStart = function(ev) {
+ var subjectEl = this.querySubjectEl(ev);
+ var downEl = ev.target;
+ if (
+ subjectEl &&
+ (!this.handleSelector || elementClosest(downEl, this.handleSelector))
+ ) {
+ this.subjectEl = subjectEl;
+ this.isDragging = true; // do this first so cancelTouchScroll will work
+ this.wasTouchScroll = false;
+ return true;
+ }
+ return false;
+ };
+ PointerDragging.prototype.cleanup = function() {
+ isWindowTouchMoveCancelled = false;
+ this.isDragging = false;
+ this.subjectEl = null;
+ // keep wasTouchScroll around for later access
+ this.destroyScrollWatch();
+ };
+ PointerDragging.prototype.querySubjectEl = function(ev) {
+ if (this.selector) {
+ return elementClosest(ev.target, this.selector);
+ }
+ return this.containerEl;
+ };
+ PointerDragging.prototype.shouldIgnoreMouse = function() {
+ return ignoreMouseDepth || this.isTouchDragging;
+ };
+ // can be called by user of this class, to cancel touch-based scrolling for the current drag
+ PointerDragging.prototype.cancelTouchScroll = function() {
+ if (this.isDragging) {
+ isWindowTouchMoveCancelled = true;
+ }
+ };
+ // Scrolling that simulates pointermoves
+ // ----------------------------------------------------------------------------------------------------
+ PointerDragging.prototype.initScrollWatch = function(ev) {
+ if (this.shouldWatchScroll) {
+ this.recordCoords(ev);
+ window.addEventListener("scroll", this.handleScroll, true); // useCapture=true
+ }
+ };
+ PointerDragging.prototype.recordCoords = function(ev) {
+ if (this.shouldWatchScroll) {
+ this.prevPageX = ev.pageX;
+ this.prevPageY = ev.pageY;
+ this.prevScrollX = window.pageXOffset;
+ this.prevScrollY = window.pageYOffset;
+ }
+ };
+ PointerDragging.prototype.destroyScrollWatch = function() {
+ if (this.shouldWatchScroll) {
+ window.removeEventListener("scroll", this.handleScroll, true); // useCaptured=true
+ }
+ };
+ // Event Normalization
+ // ----------------------------------------------------------------------------------------------------
+ PointerDragging.prototype.createEventFromMouse = function(ev, isFirst) {
+ var deltaX = 0;
+ var deltaY = 0;
+ // TODO: repeat code
+ if (isFirst) {
+ this.origPageX = ev.pageX;
+ this.origPageY = ev.pageY;
+ } else {
+ deltaX = ev.pageX - this.origPageX;
+ deltaY = ev.pageY - this.origPageY;
+ }
+ return {
+ origEvent: ev,
+ isTouch: false,
+ subjectEl: this.subjectEl,
+ pageX: ev.pageX,
+ pageY: ev.pageY,
+ deltaX: deltaX,
+ deltaY: deltaY
+ };
+ };
+ PointerDragging.prototype.createEventFromTouch = function(ev, isFirst) {
+ var touches = ev.touches;
+ var pageX;
+ var pageY;
+ var deltaX = 0;
+ var deltaY = 0;
+ // if touch coords available, prefer,
+ // because FF would give bad ev.pageX ev.pageY
+ if (touches && touches.length) {
+ pageX = touches[0].pageX;
+ pageY = touches[0].pageY;
+ } else {
+ pageX = ev.pageX;
+ pageY = ev.pageY;
+ }
+ // TODO: repeat code
+ if (isFirst) {
+ this.origPageX = pageX;
+ this.origPageY = pageY;
+ } else {
+ deltaX = pageX - this.origPageX;
+ deltaY = pageY - this.origPageY;
+ }
+ return {
+ origEvent: ev,
+ isTouch: true,
+ subjectEl: this.subjectEl,
+ pageX: pageX,
+ pageY: pageY,
+ deltaX: deltaX,
+ deltaY: deltaY
+ };
+ };
+ return PointerDragging;
+ })();
+ // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
+ function isPrimaryMouseButton(ev) {
+ return ev.button === 0 && !ev.ctrlKey;
+ }
+ // Ignoring fake mouse events generated by touch
+ // ----------------------------------------------------------------------------------------------------
+ function startIgnoringMouse() {
+ ignoreMouseDepth += 1;
+ setTimeout(function() {
+ ignoreMouseDepth -= 1;
+ }, config.touchMouseIgnoreWait);
+ }
+ // We want to attach touchmove as early as possible for Safari
+ // ----------------------------------------------------------------------------------------------------
+ function listenerCreated() {
+ listenerCnt += 1;
+ if (listenerCnt === 1) {
+ window.addEventListener("touchmove", onWindowTouchMove, {
+ passive: false
+ });
+ }
+ }
+ function listenerDestroyed() {
+ listenerCnt -= 1;
+ if (!listenerCnt) {
+ window.removeEventListener("touchmove", onWindowTouchMove, {
+ passive: false
+ });
+ }
+ }
+ function onWindowTouchMove(ev) {
+ if (isWindowTouchMoveCancelled) {
+ ev.preventDefault();
+ }
+ }
+
+ /*
+ An effect in which an element follows the movement of a pointer across the screen.
+ The moving element is a clone of some other element.
+ Must call start + handleMove + stop.
+ */
+ var ElementMirror = /** @class */ (function() {
+ function ElementMirror() {
+ this.isVisible = false; // must be explicitly enabled
+ this.sourceEl = null;
+ this.mirrorEl = null;
+ this.sourceElRect = null; // screen coords relative to viewport
+ // options that can be set directly by caller
+ this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
+ this.zIndex = 9999;
+ this.revertDuration = 0;
+ }
+ ElementMirror.prototype.start = function(sourceEl, pageX, pageY) {
+ this.sourceEl = sourceEl;
+ this.sourceElRect = this.sourceEl.getBoundingClientRect();
+ this.origScreenX = pageX - window.pageXOffset;
+ this.origScreenY = pageY - window.pageYOffset;
+ this.deltaX = 0;
+ this.deltaY = 0;
+ this.updateElPosition();
+ };
+ ElementMirror.prototype.handleMove = function(pageX, pageY) {
+ this.deltaX = pageX - window.pageXOffset - this.origScreenX;
+ this.deltaY = pageY - window.pageYOffset - this.origScreenY;
+ this.updateElPosition();
+ };
+ // can be called before start
+ ElementMirror.prototype.setIsVisible = function(bool) {
+ if (bool) {
+ if (!this.isVisible) {
+ if (this.mirrorEl) {
+ this.mirrorEl.style.display = "";
+ }
+ this.isVisible = bool; // needs to happen before updateElPosition
+ this.updateElPosition(); // because was not updating the position while invisible
+ }
+ } else if (this.isVisible) {
+ if (this.mirrorEl) {
+ this.mirrorEl.style.display = "none";
+ }
+ this.isVisible = bool;
+ }
+ };
+ // always async
+ ElementMirror.prototype.stop = function(needsRevertAnimation, callback) {
+ var _this = this;
+ var done = function() {
+ _this.cleanup();
+ callback();
+ };
+ if (
+ needsRevertAnimation &&
+ this.mirrorEl &&
+ this.isVisible &&
+ this.revertDuration && // if 0, transition won't work
+ (this.deltaX || this.deltaY) // if same coords, transition won't work
+ ) {
+ this.doRevertAnimation(done, this.revertDuration);
+ } else {
+ setTimeout(done, 0);
+ }
+ };
+ ElementMirror.prototype.doRevertAnimation = function(
+ callback,
+ revertDuration
+ ) {
+ var mirrorEl = this.mirrorEl;
+ var finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
+ mirrorEl.style.transition =
+ "top " + revertDuration + "ms," + "left " + revertDuration + "ms";
+ applyStyle(mirrorEl, {
+ left: finalSourceElRect.left,
+ top: finalSourceElRect.top
+ });
+ whenTransitionDone(mirrorEl, function() {
+ mirrorEl.style.transition = "";
+ callback();
+ });
+ };
+ ElementMirror.prototype.cleanup = function() {
+ if (this.mirrorEl) {
+ removeElement(this.mirrorEl);
+ this.mirrorEl = null;
+ }
+ this.sourceEl = null;
+ };
+ ElementMirror.prototype.updateElPosition = function() {
+ if (this.sourceEl && this.isVisible) {
+ applyStyle(this.getMirrorEl(), {
+ left: this.sourceElRect.left + this.deltaX,
+ top: this.sourceElRect.top + this.deltaY
+ });
+ }
+ };
+ ElementMirror.prototype.getMirrorEl = function() {
+ var sourceElRect = this.sourceElRect;
+ var mirrorEl = this.mirrorEl;
+ if (!mirrorEl) {
+ mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
+ // we don't want long taps or any mouse interaction causing selection/menus.
+ // would use preventSelection(), but that prevents selectstart, causing problems.
+ mirrorEl.classList.add("fc-unselectable");
+ mirrorEl.classList.add("fc-event-dragging");
+ applyStyle(mirrorEl, {
+ position: "fixed",
+ zIndex: this.zIndex,
+ visibility: "",
+ boxSizing: "border-box",
+ width: sourceElRect.right - sourceElRect.left,
+ height: sourceElRect.bottom - sourceElRect.top,
+ right: "auto",
+ bottom: "auto",
+ margin: 0
+ });
+ this.parentNode.appendChild(mirrorEl);
+ }
+ return mirrorEl;
+ };
+ return ElementMirror;
+ })();
+
+ /*
+ Is a cache for a given element's scroll information (all the info that ScrollController stores)
+ in addition the "client rectangle" of the element.. the area within the scrollbars.
+
+ The cache can be in one of two modes:
+ - doesListening:false - ignores when the container is scrolled by someone else
+ - doesListening:true - watch for scrolling and update the cache
+ */
+ var ScrollGeomCache = /** @class */ (function(_super) {
+ __extends(ScrollGeomCache, _super);
+ function ScrollGeomCache(scrollController, doesListening) {
+ var _this = _super.call(this) || this;
+ _this.handleScroll = function() {
+ _this.scrollTop = _this.scrollController.getScrollTop();
+ _this.scrollLeft = _this.scrollController.getScrollLeft();
+ _this.handleScrollChange();
+ };
+ _this.scrollController = scrollController;
+ _this.doesListening = doesListening;
+ _this.scrollTop = _this.origScrollTop = scrollController.getScrollTop();
+ _this.scrollLeft = _this.origScrollLeft = scrollController.getScrollLeft();
+ _this.scrollWidth = scrollController.getScrollWidth();
+ _this.scrollHeight = scrollController.getScrollHeight();
+ _this.clientWidth = scrollController.getClientWidth();
+ _this.clientHeight = scrollController.getClientHeight();
+ _this.clientRect = _this.computeClientRect(); // do last in case it needs cached values
+ if (_this.doesListening) {
+ _this.getEventTarget().addEventListener("scroll", _this.handleScroll);
+ }
+ return _this;
+ }
+ ScrollGeomCache.prototype.destroy = function() {
+ if (this.doesListening) {
+ this.getEventTarget().removeEventListener("scroll", this.handleScroll);
+ }
+ };
+ ScrollGeomCache.prototype.getScrollTop = function() {
+ return this.scrollTop;
+ };
+ ScrollGeomCache.prototype.getScrollLeft = function() {
+ return this.scrollLeft;
+ };
+ ScrollGeomCache.prototype.setScrollTop = function(top) {
+ this.scrollController.setScrollTop(top);
+ if (!this.doesListening) {
+ // we are not relying on the element to normalize out-of-bounds scroll values
+ // so we need to sanitize ourselves
+ this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
+ this.handleScrollChange();
+ }
+ };
+ ScrollGeomCache.prototype.setScrollLeft = function(top) {
+ this.scrollController.setScrollLeft(top);
+ if (!this.doesListening) {
+ // we are not relying on the element to normalize out-of-bounds scroll values
+ // so we need to sanitize ourselves
+ this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
+ this.handleScrollChange();
+ }
+ };
+ ScrollGeomCache.prototype.getClientWidth = function() {
+ return this.clientWidth;
+ };
+ ScrollGeomCache.prototype.getClientHeight = function() {
+ return this.clientHeight;
+ };
+ ScrollGeomCache.prototype.getScrollWidth = function() {
+ return this.scrollWidth;
+ };
+ ScrollGeomCache.prototype.getScrollHeight = function() {
+ return this.scrollHeight;
+ };
+ ScrollGeomCache.prototype.handleScrollChange = function() {};
+ return ScrollGeomCache;
+ })(ScrollController);
+
+ var ElementScrollGeomCache = /** @class */ (function(_super) {
+ __extends(ElementScrollGeomCache, _super);
+ function ElementScrollGeomCache(el, doesListening) {
+ return (
+ _super.call(this, new ElementScrollController(el), doesListening) ||
+ this
+ );
+ }
+ ElementScrollGeomCache.prototype.getEventTarget = function() {
+ return this.scrollController.el;
+ };
+ ElementScrollGeomCache.prototype.computeClientRect = function() {
+ return computeInnerRect(this.scrollController.el);
+ };
+ return ElementScrollGeomCache;
+ })(ScrollGeomCache);
+
+ var WindowScrollGeomCache = /** @class */ (function(_super) {
+ __extends(WindowScrollGeomCache, _super);
+ function WindowScrollGeomCache(doesListening) {
+ return (
+ _super.call(this, new WindowScrollController(), doesListening) || this
+ );
+ }
+ WindowScrollGeomCache.prototype.getEventTarget = function() {
+ return window;
+ };
+ WindowScrollGeomCache.prototype.computeClientRect = function() {
+ return {
+ left: this.scrollLeft,
+ right: this.scrollLeft + this.clientWidth,
+ top: this.scrollTop,
+ bottom: this.scrollTop + this.clientHeight
+ };
+ };
+ // the window is the only scroll object that changes it's rectangle relative
+ // to the document's topleft as it scrolls
+ WindowScrollGeomCache.prototype.handleScrollChange = function() {
+ this.clientRect = this.computeClientRect();
+ };
+ return WindowScrollGeomCache;
+ })(ScrollGeomCache);
+
+ // If available we are using native "performance" API instead of "Date"
+ // Read more about it on MDN:
+ // https://developer.mozilla.org/en-US/docs/Web/API/Performance
+ var getTime = typeof performance === "function" ? performance.now : Date.now;
+ /*
+ For a pointer interaction, automatically scrolls certain scroll containers when the pointer
+ approaches the edge.
+
+ The caller must call start + handleMove + stop.
+ */
+ var AutoScroller = /** @class */ (function() {
+ function AutoScroller() {
+ var _this = this;
+ // options that can be set by caller
+ this.isEnabled = true;
+ this.scrollQuery = [window, ".fc-scroller"];
+ this.edgeThreshold = 50; // pixels
+ this.maxVelocity = 300; // pixels per second
+ // internal state
+ this.pointerScreenX = null;
+ this.pointerScreenY = null;
+ this.isAnimating = false;
+ this.scrollCaches = null;
+ // protect against the initial pointerdown being too close to an edge and starting the scroll
+ this.everMovedUp = false;
+ this.everMovedDown = false;
+ this.everMovedLeft = false;
+ this.everMovedRight = false;
+ this.animate = function() {
+ if (_this.isAnimating) {
+ // wasn't cancelled between animation calls
+ var edge = _this.computeBestEdge(
+ _this.pointerScreenX + window.pageXOffset,
+ _this.pointerScreenY + window.pageYOffset
+ );
+ if (edge) {
+ var now = getTime();
+ _this.handleSide(edge, (now - _this.msSinceRequest) / 1000);
+ _this.requestAnimation(now);
+ } else {
+ _this.isAnimating = false; // will stop animation
+ }
+ }
+ };
+ }
+ AutoScroller.prototype.start = function(pageX, pageY, scrollStartEl) {
+ if (this.isEnabled) {
+ this.scrollCaches = this.buildCaches(scrollStartEl);
+ this.pointerScreenX = null;
+ this.pointerScreenY = null;
+ this.everMovedUp = false;
+ this.everMovedDown = false;
+ this.everMovedLeft = false;
+ this.everMovedRight = false;
+ this.handleMove(pageX, pageY);
+ }
+ };
+ AutoScroller.prototype.handleMove = function(pageX, pageY) {
+ if (this.isEnabled) {
+ var pointerScreenX = pageX - window.pageXOffset;
+ var pointerScreenY = pageY - window.pageYOffset;
+ var yDelta =
+ this.pointerScreenY === null
+ ? 0
+ : pointerScreenY - this.pointerScreenY;
+ var xDelta =
+ this.pointerScreenX === null
+ ? 0
+ : pointerScreenX - this.pointerScreenX;
+ if (yDelta < 0) {
+ this.everMovedUp = true;
+ } else if (yDelta > 0) {
+ this.everMovedDown = true;
+ }
+ if (xDelta < 0) {
+ this.everMovedLeft = true;
+ } else if (xDelta > 0) {
+ this.everMovedRight = true;
+ }
+ this.pointerScreenX = pointerScreenX;
+ this.pointerScreenY = pointerScreenY;
+ if (!this.isAnimating) {
+ this.isAnimating = true;
+ this.requestAnimation(getTime());
+ }
+ }
+ };
+ AutoScroller.prototype.stop = function() {
+ if (this.isEnabled) {
+ this.isAnimating = false; // will stop animation
+ for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
+ var scrollCache = _a[_i];
+ scrollCache.destroy();
+ }
+ this.scrollCaches = null;
+ }
+ };
+ AutoScroller.prototype.requestAnimation = function(now) {
+ this.msSinceRequest = now;
+ requestAnimationFrame(this.animate);
+ };
+ AutoScroller.prototype.handleSide = function(edge, seconds) {
+ var scrollCache = edge.scrollCache;
+ var edgeThreshold = this.edgeThreshold;
+ var invDistance = edgeThreshold - edge.distance;
+ var velocity = // the closer to the edge, the faster we scroll
+ ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
+ this.maxVelocity *
+ seconds;
+ var sign = 1;
+ switch (edge.name) {
+ case "left":
+ sign = -1;
+ // falls through
+ case "right":
+ scrollCache.setScrollLeft(
+ scrollCache.getScrollLeft() + velocity * sign
+ );
+ break;
+ case "top":
+ sign = -1;
+ // falls through
+ case "bottom":
+ scrollCache.setScrollTop(
+ scrollCache.getScrollTop() + velocity * sign
+ );
+ break;
+ }
+ };
+ // left/top are relative to document topleft
+ AutoScroller.prototype.computeBestEdge = function(left, top) {
+ var edgeThreshold = this.edgeThreshold;
+ var bestSide = null;
+ for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
+ var scrollCache = _a[_i];
+ var rect = scrollCache.clientRect;
+ var leftDist = left - rect.left;
+ var rightDist = rect.right - left;
+ var topDist = top - rect.top;
+ var bottomDist = rect.bottom - top;
+ // completely within the rect?
+ if (
+ leftDist >= 0 &&
+ rightDist >= 0 &&
+ topDist >= 0 &&
+ bottomDist >= 0
+ ) {
+ if (
+ topDist <= edgeThreshold &&
+ this.everMovedUp &&
+ scrollCache.canScrollUp() &&
+ (!bestSide || bestSide.distance > topDist)
+ ) {
+ bestSide = {
+ scrollCache: scrollCache,
+ name: "top",
+ distance: topDist
+ };
+ }
+ if (
+ bottomDist <= edgeThreshold &&
+ this.everMovedDown &&
+ scrollCache.canScrollDown() &&
+ (!bestSide || bestSide.distance > bottomDist)
+ ) {
+ bestSide = {
+ scrollCache: scrollCache,
+ name: "bottom",
+ distance: bottomDist
+ };
+ }
+ if (
+ leftDist <= edgeThreshold &&
+ this.everMovedLeft &&
+ scrollCache.canScrollLeft() &&
+ (!bestSide || bestSide.distance > leftDist)
+ ) {
+ bestSide = {
+ scrollCache: scrollCache,
+ name: "left",
+ distance: leftDist
+ };
+ }
+ if (
+ rightDist <= edgeThreshold &&
+ this.everMovedRight &&
+ scrollCache.canScrollRight() &&
+ (!bestSide || bestSide.distance > rightDist)
+ ) {
+ bestSide = {
+ scrollCache: scrollCache,
+ name: "right",
+ distance: rightDist
+ };
+ }
+ }
+ }
+ return bestSide;
+ };
+ AutoScroller.prototype.buildCaches = function(scrollStartEl) {
+ return this.queryScrollEls(scrollStartEl).map(function(el) {
+ if (el === window) {
+ return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
+ }
+ return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
+ });
+ };
+ AutoScroller.prototype.queryScrollEls = function(scrollStartEl) {
+ var els = [];
+ for (var _i = 0, _a = this.scrollQuery; _i < _a.length; _i++) {
+ var query = _a[_i];
+ if (typeof query === "object") {
+ els.push(query);
+ } else {
+ els.push.apply(
+ els,
+ Array.prototype.slice.call(
+ getElRoot(scrollStartEl).querySelectorAll(query)
+ )
+ );
+ }
+ }
+ return els;
+ };
+ return AutoScroller;
+ })();
+
+ /*
+ Monitors dragging on an element. Has a number of high-level features:
+ - minimum distance required before dragging
+ - minimum wait time ("delay") before dragging
+ - a mirror element that follows the pointer
+ */
+ var FeaturefulElementDragging = /** @class */ (function(_super) {
+ __extends(FeaturefulElementDragging, _super);
+ function FeaturefulElementDragging(containerEl, selector) {
+ var _this = _super.call(this, containerEl) || this;
+ _this.containerEl = containerEl;
+ // options that can be directly set by caller
+ // the caller can also set the PointerDragging's options as well
+ _this.delay = null;
+ _this.minDistance = 0;
+ _this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
+ _this.mirrorNeedsRevert = false;
+ _this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
+ _this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
+ _this.isDelayEnded = false;
+ _this.isDistanceSurpassed = false;
+ _this.delayTimeoutId = null;
+ _this.onPointerDown = function(ev) {
+ if (!_this.isDragging) {
+ // so new drag doesn't happen while revert animation is going
+ _this.isInteracting = true;
+ _this.isDelayEnded = false;
+ _this.isDistanceSurpassed = false;
+ preventSelection(document.body);
+ preventContextMenu(document.body);
+ // prevent links from being visited if there's an eventual drag.
+ // also prevents selection in older browsers (maybe?).
+ // not necessary for touch, besides, browser would complain about passiveness.
+ if (!ev.isTouch) {
+ ev.origEvent.preventDefault();
+ }
+ _this.emitter.trigger("pointerdown", ev);
+ if (
+ _this.isInteracting && // not destroyed via pointerdown handler
+ !_this.pointer.shouldIgnoreMove
+ ) {
+ // actions related to initiating dragstart+dragmove+dragend...
+ _this.mirror.setIsVisible(false); // reset. caller must set-visible
+ _this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
+ _this.startDelay(ev);
+ if (!_this.minDistance) {
+ _this.handleDistanceSurpassed(ev);
+ }
+ }
+ }
+ };
+ _this.onPointerMove = function(ev) {
+ if (_this.isInteracting) {
+ _this.emitter.trigger("pointermove", ev);
+ if (!_this.isDistanceSurpassed) {
+ var minDistance = _this.minDistance;
+ var distanceSq = void 0; // current distance from the origin, squared
+ var deltaX = ev.deltaX,
+ deltaY = ev.deltaY;
+ distanceSq = deltaX * deltaX + deltaY * deltaY;
+ if (distanceSq >= minDistance * minDistance) {
+ // use pythagorean theorem
+ _this.handleDistanceSurpassed(ev);
+ }
+ }
+ if (_this.isDragging) {
+ // a real pointer move? (not one simulated by scrolling)
+ if (ev.origEvent.type !== "scroll") {
+ _this.mirror.handleMove(ev.pageX, ev.pageY);
+ _this.autoScroller.handleMove(ev.pageX, ev.pageY);
+ }
+ _this.emitter.trigger("dragmove", ev);
+ }
+ }
+ };
+ _this.onPointerUp = function(ev) {
+ if (_this.isInteracting) {
+ _this.isInteracting = false;
+ allowSelection(document.body);
+ allowContextMenu(document.body);
+ _this.emitter.trigger("pointerup", ev); // can potentially set mirrorNeedsRevert
+ if (_this.isDragging) {
+ _this.autoScroller.stop();
+ _this.tryStopDrag(ev); // which will stop the mirror
+ }
+ if (_this.delayTimeoutId) {
+ clearTimeout(_this.delayTimeoutId);
+ _this.delayTimeoutId = null;
+ }
+ }
+ };
+ var pointer = (_this.pointer = new PointerDragging(containerEl));
+ pointer.emitter.on("pointerdown", _this.onPointerDown);
+ pointer.emitter.on("pointermove", _this.onPointerMove);
+ pointer.emitter.on("pointerup", _this.onPointerUp);
+ if (selector) {
+ pointer.selector = selector;
+ }
+ _this.mirror = new ElementMirror();
+ _this.autoScroller = new AutoScroller();
+ return _this;
+ }
+ FeaturefulElementDragging.prototype.destroy = function() {
+ this.pointer.destroy();
+ // HACK: simulate a pointer-up to end the current drag
+ // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
+ this.onPointerUp({});
+ };
+ FeaturefulElementDragging.prototype.startDelay = function(ev) {
+ var _this = this;
+ if (typeof this.delay === "number") {
+ this.delayTimeoutId = setTimeout(function() {
+ _this.delayTimeoutId = null;
+ _this.handleDelayEnd(ev);
+ }, this.delay); // not assignable to number!
+ } else {
+ this.handleDelayEnd(ev);
+ }
+ };
+ FeaturefulElementDragging.prototype.handleDelayEnd = function(ev) {
+ this.isDelayEnded = true;
+ this.tryStartDrag(ev);
+ };
+ FeaturefulElementDragging.prototype.handleDistanceSurpassed = function(ev) {
+ this.isDistanceSurpassed = true;
+ this.tryStartDrag(ev);
+ };
+ FeaturefulElementDragging.prototype.tryStartDrag = function(ev) {
+ if (this.isDelayEnded && this.isDistanceSurpassed) {
+ if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
+ this.isDragging = true;
+ this.mirrorNeedsRevert = false;
+ this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
+ this.emitter.trigger("dragstart", ev);
+ if (this.touchScrollAllowed === false) {
+ this.pointer.cancelTouchScroll();
+ }
+ }
+ }
+ };
+ FeaturefulElementDragging.prototype.tryStopDrag = function(ev) {
+ // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
+ // that come from the document to fire beforehand. much more convenient this way.
+ this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
+ };
+ FeaturefulElementDragging.prototype.stopDrag = function(ev) {
+ this.isDragging = false;
+ this.emitter.trigger("dragend", ev);
+ };
+ // fill in the implementations...
+ FeaturefulElementDragging.prototype.setIgnoreMove = function(bool) {
+ this.pointer.shouldIgnoreMove = bool;
+ };
+ FeaturefulElementDragging.prototype.setMirrorIsVisible = function(bool) {
+ this.mirror.setIsVisible(bool);
+ };
+ FeaturefulElementDragging.prototype.setMirrorNeedsRevert = function(bool) {
+ this.mirrorNeedsRevert = bool;
+ };
+ FeaturefulElementDragging.prototype.setAutoScrollEnabled = function(bool) {
+ this.autoScroller.isEnabled = bool;
+ };
+ return FeaturefulElementDragging;
+ })(ElementDragging);
+
+ /*
+ When this class is instantiated, it records the offset of an element (relative to the document topleft),
+ and continues to monitor scrolling, updating the cached coordinates if it needs to.
+ Does not access the DOM after instantiation, so highly performant.
+
+ Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
+ and an determine if a given point is inside the combined clipping rectangle.
+ */
+ var OffsetTracker = /** @class */ (function() {
+ function OffsetTracker(el) {
+ this.origRect = computeRect(el);
+ // will work fine for divs that have overflow:hidden
+ this.scrollCaches = getClippingParents(el).map(function(scrollEl) {
+ return new ElementScrollGeomCache(scrollEl, true);
+ });
+ }
+ OffsetTracker.prototype.destroy = function() {
+ for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
+ var scrollCache = _a[_i];
+ scrollCache.destroy();
+ }
+ };
+ OffsetTracker.prototype.computeLeft = function() {
+ var left = this.origRect.left;
+ for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
+ var scrollCache = _a[_i];
+ left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
+ }
+ return left;
+ };
+ OffsetTracker.prototype.computeTop = function() {
+ var top = this.origRect.top;
+ for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
+ var scrollCache = _a[_i];
+ top += scrollCache.origScrollTop - scrollCache.getScrollTop();
+ }
+ return top;
+ };
+ OffsetTracker.prototype.isWithinClipping = function(pageX, pageY) {
+ var point = { left: pageX, top: pageY };
+ for (var _i = 0, _a = this.scrollCaches; _i < _a.length; _i++) {
+ var scrollCache = _a[_i];
+ if (
+ !isIgnoredClipping(scrollCache.getEventTarget()) &&
+ !pointInsideRect(point, scrollCache.clientRect)
+ ) {
+ return false;
+ }
+ }
+ return true;
+ };
+ return OffsetTracker;
+ })();
+ // certain clipping containers should never constrain interactions, like and
+ // https://github.com/fullcalendar/fullcalendar/issues/3615
+ function isIgnoredClipping(node) {
+ var tagName = node.tagName;
+ return tagName === "HTML" || tagName === "BODY";
+ }
+
+ /*
+ Tracks movement over multiple droppable areas (aka "hits")
+ that exist in one or more DateComponents.
+ Relies on an existing draggable.
+
+ emits:
+ - pointerdown
+ - dragstart
+ - hitchange - fires initially, even if not over a hit
+ - pointerup
+ - (hitchange - again, to null, if ended over a hit)
+ - dragend
+ */
+ var HitDragging = /** @class */ (function() {
+ function HitDragging(dragging, droppableStore) {
+ var _this = this;
+ // options that can be set by caller
+ this.useSubjectCenter = false;
+ this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
+ this.initialHit = null;
+ this.movingHit = null;
+ this.finalHit = null; // won't ever be populated if shouldIgnoreMove
+ this.handlePointerDown = function(ev) {
+ var dragging = _this.dragging;
+ _this.initialHit = null;
+ _this.movingHit = null;
+ _this.finalHit = null;
+ _this.prepareHits();
+ _this.processFirstCoord(ev);
+ if (_this.initialHit || !_this.requireInitial) {
+ dragging.setIgnoreMove(false);
+ // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
+ _this.emitter.trigger("pointerdown", ev);
+ } else {
+ dragging.setIgnoreMove(true);
+ }
+ };
+ this.handleDragStart = function(ev) {
+ _this.emitter.trigger("dragstart", ev);
+ _this.handleMove(ev, true); // force = fire even if initially null
+ };
+ this.handleDragMove = function(ev) {
+ _this.emitter.trigger("dragmove", ev);
+ _this.handleMove(ev);
+ };
+ this.handlePointerUp = function(ev) {
+ _this.releaseHits();
+ _this.emitter.trigger("pointerup", ev);
+ };
+ this.handleDragEnd = function(ev) {
+ if (_this.movingHit) {
+ _this.emitter.trigger("hitupdate", null, true, ev);
+ }
+ _this.finalHit = _this.movingHit;
+ _this.movingHit = null;
+ _this.emitter.trigger("dragend", ev);
+ };
+ this.droppableStore = droppableStore;
+ dragging.emitter.on("pointerdown", this.handlePointerDown);
+ dragging.emitter.on("dragstart", this.handleDragStart);
+ dragging.emitter.on("dragmove", this.handleDragMove);
+ dragging.emitter.on("pointerup", this.handlePointerUp);
+ dragging.emitter.on("dragend", this.handleDragEnd);
+ this.dragging = dragging;
+ this.emitter = new Emitter();
+ }
+ // sets initialHit
+ // sets coordAdjust
+ HitDragging.prototype.processFirstCoord = function(ev) {
+ var origPoint = { left: ev.pageX, top: ev.pageY };
+ var adjustedPoint = origPoint;
+ var subjectEl = ev.subjectEl;
+ var subjectRect;
+ if (subjectEl instanceof HTMLElement) {
+ // i.e. not a Document/ShadowRoot
+ subjectRect = computeRect(subjectEl);
+ adjustedPoint = constrainPoint(adjustedPoint, subjectRect);
+ }
+ var initialHit = (this.initialHit = this.queryHitForOffset(
+ adjustedPoint.left,
+ adjustedPoint.top
+ ));
+ if (initialHit) {
+ if (this.useSubjectCenter && subjectRect) {
+ var slicedSubjectRect = intersectRects(subjectRect, initialHit.rect);
+ if (slicedSubjectRect) {
+ adjustedPoint = getRectCenter(slicedSubjectRect);
+ }
+ }
+ this.coordAdjust = diffPoints(adjustedPoint, origPoint);
+ } else {
+ this.coordAdjust = { left: 0, top: 0 };
+ }
+ };
+ HitDragging.prototype.handleMove = function(ev, forceHandle) {
+ var hit = this.queryHitForOffset(
+ ev.pageX + this.coordAdjust.left,
+ ev.pageY + this.coordAdjust.top
+ );
+ if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
+ this.movingHit = hit;
+ this.emitter.trigger("hitupdate", hit, false, ev);
+ }
+ };
+ HitDragging.prototype.prepareHits = function() {
+ this.offsetTrackers = mapHash(this.droppableStore, function(
+ interactionSettings
+ ) {
+ interactionSettings.component.prepareHits();
+ return new OffsetTracker(interactionSettings.el);
+ });
+ };
+ HitDragging.prototype.releaseHits = function() {
+ var offsetTrackers = this.offsetTrackers;
+ for (var id in offsetTrackers) {
+ offsetTrackers[id].destroy();
+ }
+ this.offsetTrackers = {};
+ };
+ HitDragging.prototype.queryHitForOffset = function(offsetLeft, offsetTop) {
+ var _a = this,
+ droppableStore = _a.droppableStore,
+ offsetTrackers = _a.offsetTrackers;
+ var bestHit = null;
+ for (var id in droppableStore) {
+ var component = droppableStore[id].component;
+ var offsetTracker = offsetTrackers[id];
+ if (
+ offsetTracker && // wasn't destroyed mid-drag
+ offsetTracker.isWithinClipping(offsetLeft, offsetTop)
+ ) {
+ var originLeft = offsetTracker.computeLeft();
+ var originTop = offsetTracker.computeTop();
+ var positionLeft = offsetLeft - originLeft;
+ var positionTop = offsetTop - originTop;
+ var origRect = offsetTracker.origRect;
+ var width = origRect.right - origRect.left;
+ var height = origRect.bottom - origRect.top;
+ if (
+ // must be within the element's bounds
+ positionLeft >= 0 &&
+ positionLeft < width &&
+ positionTop >= 0 &&
+ positionTop < height
+ ) {
+ var hit = component.queryHit(
+ positionLeft,
+ positionTop,
+ width,
+ height
+ );
+ if (
+ hit &&
+ // make sure the hit is within activeRange, meaning it's not a dead cell
+ rangeContainsRange(
+ hit.dateProfile.activeRange,
+ hit.dateSpan.range
+ ) &&
+ (!bestHit || hit.layer > bestHit.layer)
+ ) {
+ hit.componentId = id;
+ hit.context = component.context;
+ // TODO: better way to re-orient rectangle
+ hit.rect.left += originLeft;
+ hit.rect.right += originLeft;
+ hit.rect.top += originTop;
+ hit.rect.bottom += originTop;
+ bestHit = hit;
+ }
+ }
+ }
+ }
+ return bestHit;
+ };
+ return HitDragging;
+ })();
+ function isHitsEqual(hit0, hit1) {
+ if (!hit0 && !hit1) {
+ return true;
+ }
+ if (Boolean(hit0) !== Boolean(hit1)) {
+ return false;
+ }
+ return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
+ }
+
+ function buildDatePointApiWithContext(dateSpan, context) {
+ var props = {};
+ for (
+ var _i = 0, _a = context.pluginHooks.datePointTransforms;
+ _i < _a.length;
+ _i++
+ ) {
+ var transform = _a[_i];
+ __assign(props, transform(dateSpan, context));
+ }
+ __assign(props, buildDatePointApi(dateSpan, context.dateEnv));
+ return props;
+ }
+ function buildDatePointApi(span, dateEnv) {
+ return {
+ date: dateEnv.toDate(span.range.start),
+ dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
+ allDay: span.allDay
+ };
+ }
+
+ /*
+ Monitors when the user clicks on a specific date/time of a component.
+ A pointerdown+pointerup on the same "hit" constitutes a click.
+ */
+ var DateClicking = /** @class */ (function(_super) {
+ __extends(DateClicking, _super);
+ function DateClicking(settings) {
+ var _this = _super.call(this, settings) || this;
+ _this.handlePointerDown = function(pev) {
+ var dragging = _this.dragging;
+ var downEl = pev.origEvent.target;
+ // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
+ dragging.setIgnoreMove(!_this.component.isValidDateDownEl(downEl));
+ };
+ // won't even fire if moving was ignored
+ _this.handleDragEnd = function(ev) {
+ var component = _this.component;
+ var pointer = _this.dragging.pointer;
+ if (!pointer.wasTouchScroll) {
+ var _a = _this.hitDragging,
+ initialHit = _a.initialHit,
+ finalHit = _a.finalHit;
+ if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
+ var context = component.context;
+ var arg = __assign(
+ __assign(
+ {},
+ buildDatePointApiWithContext(initialHit.dateSpan, context)
+ ),
+ {
+ dayEl: initialHit.dayEl,
+ jsEvent: ev.origEvent,
+ view: context.viewApi || context.calendarApi.view
+ }
+ );
+ context.emitter.trigger("dateClick", arg);
+ }
+ }
+ };
+ // we DO want to watch pointer moves because otherwise finalHit won't get populated
+ _this.dragging = new FeaturefulElementDragging(settings.el);
+ _this.dragging.autoScroller.isEnabled = false;
+ var hitDragging = (_this.hitDragging = new HitDragging(
+ _this.dragging,
+ interactionSettingsToStore(settings)
+ ));
+ hitDragging.emitter.on("pointerdown", _this.handlePointerDown);
+ hitDragging.emitter.on("dragend", _this.handleDragEnd);
+ return _this;
+ }
+ DateClicking.prototype.destroy = function() {
+ this.dragging.destroy();
+ };
+ return DateClicking;
+ })(Interaction);
+
+ /*
+ Tracks when the user selects a portion of time of a component,
+ constituted by a drag over date cells, with a possible delay at the beginning of the drag.
+ */
+ var DateSelecting = /** @class */ (function(_super) {
+ __extends(DateSelecting, _super);
+ function DateSelecting(settings) {
+ var _this = _super.call(this, settings) || this;
+ _this.dragSelection = null;
+ _this.handlePointerDown = function(ev) {
+ var _a = _this,
+ component = _a.component,
+ dragging = _a.dragging;
+ var options = component.context.options;
+ var canSelect =
+ options.selectable &&
+ component.isValidDateDownEl(ev.origEvent.target);
+ // don't bother to watch expensive moves if component won't do selection
+ dragging.setIgnoreMove(!canSelect);
+ // if touch, require user to hold down
+ dragging.delay = ev.isTouch
+ ? getComponentTouchDelay$1(component)
+ : null;
+ };
+ _this.handleDragStart = function(ev) {
+ _this.component.context.calendarApi.unselect(ev); // unselect previous selections
+ };
+ _this.handleHitUpdate = function(hit, isFinal) {
+ var context = _this.component.context;
+ var dragSelection = null;
+ var isInvalid = false;
+ if (hit) {
+ var initialHit = _this.hitDragging.initialHit;
+ var disallowed =
+ hit.componentId === initialHit.componentId &&
+ _this.isHitComboAllowed &&
+ !_this.isHitComboAllowed(initialHit, hit);
+ if (!disallowed) {
+ dragSelection = joinHitsIntoSelection(
+ initialHit,
+ hit,
+ context.pluginHooks.dateSelectionTransformers
+ );
+ }
+ if (
+ !dragSelection ||
+ !isDateSelectionValid(dragSelection, hit.dateProfile, context)
+ ) {
+ isInvalid = true;
+ dragSelection = null;
+ }
+ }
+ if (dragSelection) {
+ context.dispatch({ type: "SELECT_DATES", selection: dragSelection });
+ } else if (!isFinal) {
+ // only unselect if moved away while dragging
+ context.dispatch({ type: "UNSELECT_DATES" });
+ }
+ if (!isInvalid) {
+ enableCursor();
+ } else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ _this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
+ }
+ };
+ _this.handlePointerUp = function(pev) {
+ if (_this.dragSelection) {
+ // selection is already rendered, so just need to report selection
+ triggerDateSelect(_this.dragSelection, pev, _this.component.context);
+ _this.dragSelection = null;
+ }
+ };
+ var component = settings.component;
+ var options = component.context.options;
+ var dragging = (_this.dragging = new FeaturefulElementDragging(
+ settings.el
+ ));
+ dragging.touchScrollAllowed = false;
+ dragging.minDistance = options.selectMinDistance || 0;
+ dragging.autoScroller.isEnabled = options.dragScroll;
+ var hitDragging = (_this.hitDragging = new HitDragging(
+ _this.dragging,
+ interactionSettingsToStore(settings)
+ ));
+ hitDragging.emitter.on("pointerdown", _this.handlePointerDown);
+ hitDragging.emitter.on("dragstart", _this.handleDragStart);
+ hitDragging.emitter.on("hitupdate", _this.handleHitUpdate);
+ hitDragging.emitter.on("pointerup", _this.handlePointerUp);
+ return _this;
+ }
+ DateSelecting.prototype.destroy = function() {
+ this.dragging.destroy();
+ };
+ return DateSelecting;
+ })(Interaction);
+ function getComponentTouchDelay$1(component) {
+ var options = component.context.options;
+ var delay = options.selectLongPressDelay;
+ if (delay == null) {
+ delay = options.longPressDelay;
+ }
+ return delay;
+ }
+ function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
+ var dateSpan0 = hit0.dateSpan;
+ var dateSpan1 = hit1.dateSpan;
+ var ms = [
+ dateSpan0.range.start,
+ dateSpan0.range.end,
+ dateSpan1.range.start,
+ dateSpan1.range.end
+ ];
+ ms.sort(compareNumbers);
+ var props = {};
+ for (
+ var _i = 0, dateSelectionTransformers_1 = dateSelectionTransformers;
+ _i < dateSelectionTransformers_1.length;
+ _i++
+ ) {
+ var transformer = dateSelectionTransformers_1[_i];
+ var res = transformer(hit0, hit1);
+ if (res === false) {
+ return null;
+ }
+ if (res) {
+ __assign(props, res);
+ }
+ }
+ props.range = { start: ms[0], end: ms[3] };
+ props.allDay = dateSpan0.allDay;
+ return props;
+ }
+
+ var EventDragging = /** @class */ (function(_super) {
+ __extends(EventDragging, _super);
+ function EventDragging(settings) {
+ var _this = _super.call(this, settings) || this;
+ // internal state
+ _this.subjectEl = null;
+ _this.subjectSeg = null; // the seg being selected/dragged
+ _this.isDragging = false;
+ _this.eventRange = null;
+ _this.relevantEvents = null; // the events being dragged
+ _this.receivingContext = null;
+ _this.validMutation = null;
+ _this.mutatedRelevantEvents = null;
+ _this.handlePointerDown = function(ev) {
+ var origTarget = ev.origEvent.target;
+ var _a = _this,
+ component = _a.component,
+ dragging = _a.dragging;
+ var mirror = dragging.mirror;
+ var options = component.context.options;
+ var initialContext = component.context;
+ _this.subjectEl = ev.subjectEl;
+ var subjectSeg = (_this.subjectSeg = getElSeg(ev.subjectEl));
+ var eventRange = (_this.eventRange = subjectSeg.eventRange);
+ var eventInstanceId = eventRange.instance.instanceId;
+ _this.relevantEvents = getRelevantEvents(
+ initialContext.getCurrentData().eventStore,
+ eventInstanceId
+ );
+ dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
+ dragging.delay =
+ // only do a touch delay if touch and this event hasn't been selected yet
+ ev.isTouch && eventInstanceId !== component.props.eventSelection
+ ? getComponentTouchDelay(component)
+ : null;
+ if (options.fixedMirrorParent) {
+ mirror.parentNode = options.fixedMirrorParent;
+ } else {
+ mirror.parentNode = elementClosest(origTarget, ".fc");
+ }
+ mirror.revertDuration = options.dragRevertDuration;
+ var isValid =
+ component.isValidSegDownEl(origTarget) &&
+ !elementClosest(origTarget, ".fc-event-resizer"); // NOT on a resizer
+ dragging.setIgnoreMove(!isValid);
+ // disable dragging for elements that are resizable (ie, selectable)
+ // but are not draggable
+ _this.isDragging =
+ isValid && ev.subjectEl.classList.contains("fc-event-draggable");
+ };
+ _this.handleDragStart = function(ev) {
+ var initialContext = _this.component.context;
+ var eventRange = _this.eventRange;
+ var eventInstanceId = eventRange.instance.instanceId;
+ if (ev.isTouch) {
+ // need to select a different event?
+ if (eventInstanceId !== _this.component.props.eventSelection) {
+ initialContext.dispatch({
+ type: "SELECT_EVENT",
+ eventInstanceId: eventInstanceId
+ });
+ }
+ } else {
+ // if now using mouse, but was previous touch interaction, clear selected event
+ initialContext.dispatch({ type: "UNSELECT_EVENT" });
+ }
+ if (_this.isDragging) {
+ initialContext.calendarApi.unselect(ev); // unselect *date* selection
+ initialContext.emitter.trigger("eventDragStart", {
+ el: _this.subjectEl,
+ event: new EventApi(
+ initialContext,
+ eventRange.def,
+ eventRange.instance
+ ),
+ jsEvent: ev.origEvent,
+ view: initialContext.viewApi
+ });
+ }
+ };
+ _this.handleHitUpdate = function(hit, isFinal) {
+ if (!_this.isDragging) {
+ return;
+ }
+ var relevantEvents = _this.relevantEvents;
+ var initialHit = _this.hitDragging.initialHit;
+ var initialContext = _this.component.context;
+ // states based on new hit
+ var receivingContext = null;
+ var mutation = null;
+ var mutatedRelevantEvents = null;
+ var isInvalid = false;
+ var interaction = {
+ affectedEvents: relevantEvents,
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: true
+ };
+ if (hit) {
+ receivingContext = hit.context;
+ var receivingOptions = receivingContext.options;
+ if (
+ initialContext === receivingContext ||
+ (receivingOptions.editable && receivingOptions.droppable)
+ ) {
+ mutation = computeEventMutation(
+ initialHit,
+ hit,
+ receivingContext.getCurrentData().pluginHooks
+ .eventDragMutationMassagers
+ );
+ if (mutation) {
+ mutatedRelevantEvents = applyMutationToEventStore(
+ relevantEvents,
+ receivingContext.getCurrentData().eventUiBases,
+ mutation,
+ receivingContext
+ );
+ interaction.mutatedEvents = mutatedRelevantEvents;
+ if (
+ !isInteractionValid(
+ interaction,
+ hit.dateProfile,
+ receivingContext
+ )
+ ) {
+ isInvalid = true;
+ mutation = null;
+ mutatedRelevantEvents = null;
+ interaction.mutatedEvents = createEmptyEventStore();
+ }
+ }
+ } else {
+ receivingContext = null;
+ }
+ }
+ _this.displayDrag(receivingContext, interaction);
+ if (!isInvalid) {
+ enableCursor();
+ } else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ if (
+ initialContext === receivingContext && // TODO: write test for this
+ isHitsEqual(initialHit, hit)
+ ) {
+ mutation = null;
+ }
+ _this.dragging.setMirrorNeedsRevert(!mutation);
+ // render the mirror if no already-rendered mirror
+ // TODO: wish we could somehow wait for dispatch to guarantee render
+ _this.dragging.setMirrorIsVisible(
+ !hit ||
+ !getElRoot(_this.subjectEl).querySelector(".fc-event-mirror")
+ );
+ // assign states based on new hit
+ _this.receivingContext = receivingContext;
+ _this.validMutation = mutation;
+ _this.mutatedRelevantEvents = mutatedRelevantEvents;
+ }
+ };
+ _this.handlePointerUp = function() {
+ if (!_this.isDragging) {
+ _this.cleanup(); // because handleDragEnd won't fire
+ }
+ };
+ _this.handleDragEnd = function(ev) {
+ if (_this.isDragging) {
+ var initialContext_1 = _this.component.context;
+ var initialView = initialContext_1.viewApi;
+ var _a = _this,
+ receivingContext_1 = _a.receivingContext,
+ validMutation = _a.validMutation;
+ var eventDef = _this.eventRange.def;
+ var eventInstance = _this.eventRange.instance;
+ var eventApi = new EventApi(
+ initialContext_1,
+ eventDef,
+ eventInstance
+ );
+ var relevantEvents_1 = _this.relevantEvents;
+ var mutatedRelevantEvents_1 = _this.mutatedRelevantEvents;
+ var finalHit = _this.hitDragging.finalHit;
+ _this.clearDrag(); // must happen after revert animation
+ initialContext_1.emitter.trigger("eventDragStop", {
+ el: _this.subjectEl,
+ event: eventApi,
+ jsEvent: ev.origEvent,
+ view: initialView
+ });
+ if (validMutation) {
+ // dropped within same calendar
+ if (receivingContext_1 === initialContext_1) {
+ var updatedEventApi = new EventApi(
+ initialContext_1,
+ mutatedRelevantEvents_1.defs[eventDef.defId],
+ eventInstance
+ ? mutatedRelevantEvents_1.instances[eventInstance.instanceId]
+ : null
+ );
+ initialContext_1.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: mutatedRelevantEvents_1
+ });
+ var eventChangeArg = {
+ oldEvent: eventApi,
+ event: updatedEventApi,
+ relatedEvents: buildEventApis(
+ mutatedRelevantEvents_1,
+ initialContext_1,
+ eventInstance
+ ),
+ revert: function() {
+ initialContext_1.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: relevantEvents_1 // the pre-change data
+ });
+ }
+ };
+ var transformed = {};
+ for (
+ var _i = 0,
+ _b = initialContext_1.getCurrentData().pluginHooks
+ .eventDropTransformers;
+ _i < _b.length;
+ _i++
+ ) {
+ var transformer = _b[_i];
+ __assign(
+ transformed,
+ transformer(validMutation, initialContext_1)
+ );
+ }
+ initialContext_1.emitter.trigger(
+ "eventDrop",
+ __assign(__assign(__assign({}, eventChangeArg), transformed), {
+ el: ev.subjectEl,
+ delta: validMutation.datesDelta,
+ jsEvent: ev.origEvent,
+ view: initialView
+ })
+ );
+ initialContext_1.emitter.trigger("eventChange", eventChangeArg);
+ // dropped in different calendar
+ } else if (receivingContext_1) {
+ var eventRemoveArg = {
+ event: eventApi,
+ relatedEvents: buildEventApis(
+ relevantEvents_1,
+ initialContext_1,
+ eventInstance
+ ),
+ revert: function() {
+ initialContext_1.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: relevantEvents_1
+ });
+ }
+ };
+ initialContext_1.emitter.trigger(
+ "eventLeave",
+ __assign(__assign({}, eventRemoveArg), {
+ draggedEl: ev.subjectEl,
+ view: initialView
+ })
+ );
+ initialContext_1.dispatch({
+ type: "REMOVE_EVENTS",
+ eventStore: relevantEvents_1
+ });
+ initialContext_1.emitter.trigger("eventRemove", eventRemoveArg);
+ var addedEventDef = mutatedRelevantEvents_1.defs[eventDef.defId];
+ var addedEventInstance =
+ mutatedRelevantEvents_1.instances[eventInstance.instanceId];
+ var addedEventApi = new EventApi(
+ receivingContext_1,
+ addedEventDef,
+ addedEventInstance
+ );
+ receivingContext_1.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: mutatedRelevantEvents_1
+ });
+ var eventAddArg = {
+ event: addedEventApi,
+ relatedEvents: buildEventApis(
+ mutatedRelevantEvents_1,
+ receivingContext_1,
+ addedEventInstance
+ ),
+ revert: function() {
+ receivingContext_1.dispatch({
+ type: "REMOVE_EVENTS",
+ eventStore: mutatedRelevantEvents_1
+ });
+ }
+ };
+ receivingContext_1.emitter.trigger("eventAdd", eventAddArg);
+ if (ev.isTouch) {
+ receivingContext_1.dispatch({
+ type: "SELECT_EVENT",
+ eventInstanceId: eventInstance.instanceId
+ });
+ }
+ receivingContext_1.emitter.trigger(
+ "drop",
+ __assign(
+ __assign(
+ {},
+ buildDatePointApiWithContext(
+ finalHit.dateSpan,
+ receivingContext_1
+ )
+ ),
+ {
+ draggedEl: ev.subjectEl,
+ jsEvent: ev.origEvent,
+ view: finalHit.context.viewApi
+ }
+ )
+ );
+ receivingContext_1.emitter.trigger(
+ "eventReceive",
+ __assign(__assign({}, eventAddArg), {
+ draggedEl: ev.subjectEl,
+ view: finalHit.context.viewApi
+ })
+ );
+ }
+ } else {
+ initialContext_1.emitter.trigger("_noEventDrop");
+ }
+ }
+ _this.cleanup();
+ };
+ var component = _this.component;
+ var options = component.context.options;
+ var dragging = (_this.dragging = new FeaturefulElementDragging(
+ settings.el
+ ));
+ dragging.pointer.selector = EventDragging.SELECTOR;
+ dragging.touchScrollAllowed = false;
+ dragging.autoScroller.isEnabled = options.dragScroll;
+ var hitDragging = (_this.hitDragging = new HitDragging(
+ _this.dragging,
+ interactionSettingsStore
+ ));
+ hitDragging.useSubjectCenter = settings.useEventCenter;
+ hitDragging.emitter.on("pointerdown", _this.handlePointerDown);
+ hitDragging.emitter.on("dragstart", _this.handleDragStart);
+ hitDragging.emitter.on("hitupdate", _this.handleHitUpdate);
+ hitDragging.emitter.on("pointerup", _this.handlePointerUp);
+ hitDragging.emitter.on("dragend", _this.handleDragEnd);
+ return _this;
+ }
+ EventDragging.prototype.destroy = function() {
+ this.dragging.destroy();
+ };
+ // render a drag state on the next receivingCalendar
+ EventDragging.prototype.displayDrag = function(nextContext, state) {
+ var initialContext = this.component.context;
+ var prevContext = this.receivingContext;
+ // does the previous calendar need to be cleared?
+ if (prevContext && prevContext !== nextContext) {
+ // does the initial calendar need to be cleared?
+ // if so, don't clear all the way. we still need to to hide the affectedEvents
+ if (prevContext === initialContext) {
+ prevContext.dispatch({
+ type: "SET_EVENT_DRAG",
+ state: {
+ affectedEvents: state.affectedEvents,
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: true
+ }
+ });
+ // completely clear the old calendar if it wasn't the initial
+ } else {
+ prevContext.dispatch({ type: "UNSET_EVENT_DRAG" });
+ }
+ }
+ if (nextContext) {
+ nextContext.dispatch({ type: "SET_EVENT_DRAG", state: state });
+ }
+ };
+ EventDragging.prototype.clearDrag = function() {
+ var initialCalendar = this.component.context;
+ var receivingContext = this.receivingContext;
+ if (receivingContext) {
+ receivingContext.dispatch({ type: "UNSET_EVENT_DRAG" });
+ }
+ // the initial calendar might have an dummy drag state from displayDrag
+ if (initialCalendar !== receivingContext) {
+ initialCalendar.dispatch({ type: "UNSET_EVENT_DRAG" });
+ }
+ };
+ EventDragging.prototype.cleanup = function() {
+ this.subjectSeg = null;
+ this.isDragging = false;
+ this.eventRange = null;
+ this.relevantEvents = null;
+ this.receivingContext = null;
+ this.validMutation = null;
+ this.mutatedRelevantEvents = null;
+ };
+ // TODO: test this in IE11
+ // QUESTION: why do we need it on the resizable???
+ EventDragging.SELECTOR = ".fc-event-draggable, .fc-event-resizable";
+ return EventDragging;
+ })(Interaction);
+ function computeEventMutation(hit0, hit1, massagers) {
+ var dateSpan0 = hit0.dateSpan;
+ var dateSpan1 = hit1.dateSpan;
+ var date0 = dateSpan0.range.start;
+ var date1 = dateSpan1.range.start;
+ var standardProps = {};
+ if (dateSpan0.allDay !== dateSpan1.allDay) {
+ standardProps.allDay = dateSpan1.allDay;
+ standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
+ if (dateSpan1.allDay) {
+ // means date1 is already start-of-day,
+ // but date0 needs to be converted
+ date0 = startOfDay(date0);
+ }
+ }
+ var delta = diffDates(
+ date0,
+ date1,
+ hit0.context.dateEnv,
+ hit0.componentId === hit1.componentId ? hit0.largeUnit : null
+ );
+ if (delta.milliseconds) {
+ // has hours/minutes/seconds
+ standardProps.allDay = false;
+ }
+ var mutation = {
+ datesDelta: delta,
+ standardProps: standardProps
+ };
+ for (var _i = 0, massagers_1 = massagers; _i < massagers_1.length; _i++) {
+ var massager = massagers_1[_i];
+ massager(mutation, hit0, hit1);
+ }
+ return mutation;
+ }
+ function getComponentTouchDelay(component) {
+ var options = component.context.options;
+ var delay = options.eventLongPressDelay;
+ if (delay == null) {
+ delay = options.longPressDelay;
+ }
+ return delay;
+ }
+
+ var EventResizing = /** @class */ (function(_super) {
+ __extends(EventResizing, _super);
+ function EventResizing(settings) {
+ var _this = _super.call(this, settings) || this;
+ // internal state
+ _this.draggingSegEl = null;
+ _this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
+ _this.eventRange = null;
+ _this.relevantEvents = null;
+ _this.validMutation = null;
+ _this.mutatedRelevantEvents = null;
+ _this.handlePointerDown = function(ev) {
+ var component = _this.component;
+ var segEl = _this.querySegEl(ev);
+ var seg = getElSeg(segEl);
+ var eventRange = (_this.eventRange = seg.eventRange);
+ _this.dragging.minDistance =
+ component.context.options.eventDragMinDistance;
+ // if touch, need to be working with a selected event
+ _this.dragging.setIgnoreMove(
+ !_this.component.isValidSegDownEl(ev.origEvent.target) ||
+ (ev.isTouch &&
+ _this.component.props.eventSelection !==
+ eventRange.instance.instanceId)
+ );
+ };
+ _this.handleDragStart = function(ev) {
+ var context = _this.component.context;
+ var eventRange = _this.eventRange;
+ _this.relevantEvents = getRelevantEvents(
+ context.getCurrentData().eventStore,
+ _this.eventRange.instance.instanceId
+ );
+ var segEl = _this.querySegEl(ev);
+ _this.draggingSegEl = segEl;
+ _this.draggingSeg = getElSeg(segEl);
+ context.calendarApi.unselect();
+ context.emitter.trigger("eventResizeStart", {
+ el: segEl,
+ event: new EventApi(context, eventRange.def, eventRange.instance),
+ jsEvent: ev.origEvent,
+ view: context.viewApi
+ });
+ };
+ _this.handleHitUpdate = function(hit, isFinal, ev) {
+ var context = _this.component.context;
+ var relevantEvents = _this.relevantEvents;
+ var initialHit = _this.hitDragging.initialHit;
+ var eventInstance = _this.eventRange.instance;
+ var mutation = null;
+ var mutatedRelevantEvents = null;
+ var isInvalid = false;
+ var interaction = {
+ affectedEvents: relevantEvents,
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: true
+ };
+ if (hit) {
+ var disallowed =
+ hit.componentId === initialHit.componentId &&
+ _this.isHitComboAllowed &&
+ !_this.isHitComboAllowed(initialHit, hit);
+ if (!disallowed) {
+ mutation = computeMutation(
+ initialHit,
+ hit,
+ ev.subjectEl.classList.contains("fc-event-resizer-start"),
+ eventInstance.range
+ );
+ }
+ }
+ if (mutation) {
+ mutatedRelevantEvents = applyMutationToEventStore(
+ relevantEvents,
+ context.getCurrentData().eventUiBases,
+ mutation,
+ context
+ );
+ interaction.mutatedEvents = mutatedRelevantEvents;
+ if (!isInteractionValid(interaction, hit.dateProfile, context)) {
+ isInvalid = true;
+ mutation = null;
+ mutatedRelevantEvents = null;
+ interaction.mutatedEvents = null;
+ }
+ }
+ if (mutatedRelevantEvents) {
+ context.dispatch({
+ type: "SET_EVENT_RESIZE",
+ state: interaction
+ });
+ } else {
+ context.dispatch({ type: "UNSET_EVENT_RESIZE" });
+ }
+ if (!isInvalid) {
+ enableCursor();
+ } else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ if (mutation && isHitsEqual(initialHit, hit)) {
+ mutation = null;
+ }
+ _this.validMutation = mutation;
+ _this.mutatedRelevantEvents = mutatedRelevantEvents;
+ }
+ };
+ _this.handleDragEnd = function(ev) {
+ var context = _this.component.context;
+ var eventDef = _this.eventRange.def;
+ var eventInstance = _this.eventRange.instance;
+ var eventApi = new EventApi(context, eventDef, eventInstance);
+ var relevantEvents = _this.relevantEvents;
+ var mutatedRelevantEvents = _this.mutatedRelevantEvents;
+ context.emitter.trigger("eventResizeStop", {
+ el: _this.draggingSegEl,
+ event: eventApi,
+ jsEvent: ev.origEvent,
+ view: context.viewApi
+ });
+ if (_this.validMutation) {
+ var updatedEventApi = new EventApi(
+ context,
+ mutatedRelevantEvents.defs[eventDef.defId],
+ eventInstance
+ ? mutatedRelevantEvents.instances[eventInstance.instanceId]
+ : null
+ );
+ context.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: mutatedRelevantEvents
+ });
+ var eventChangeArg = {
+ oldEvent: eventApi,
+ event: updatedEventApi,
+ relatedEvents: buildEventApis(
+ mutatedRelevantEvents,
+ context,
+ eventInstance
+ ),
+ revert: function() {
+ context.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: relevantEvents // the pre-change events
+ });
+ }
+ };
+ context.emitter.trigger(
+ "eventResize",
+ __assign(__assign({}, eventChangeArg), {
+ el: _this.draggingSegEl,
+ startDelta: _this.validMutation.startDelta || createDuration(0),
+ endDelta: _this.validMutation.endDelta || createDuration(0),
+ jsEvent: ev.origEvent,
+ view: context.viewApi
+ })
+ );
+ context.emitter.trigger("eventChange", eventChangeArg);
+ } else {
+ context.emitter.trigger("_noEventResize");
+ }
+ // reset all internal state
+ _this.draggingSeg = null;
+ _this.relevantEvents = null;
+ _this.validMutation = null;
+ // okay to keep eventInstance around. useful to set it in handlePointerDown
+ };
+ var component = settings.component;
+ var dragging = (_this.dragging = new FeaturefulElementDragging(
+ settings.el
+ ));
+ dragging.pointer.selector = ".fc-event-resizer";
+ dragging.touchScrollAllowed = false;
+ dragging.autoScroller.isEnabled = component.context.options.dragScroll;
+ var hitDragging = (_this.hitDragging = new HitDragging(
+ _this.dragging,
+ interactionSettingsToStore(settings)
+ ));
+ hitDragging.emitter.on("pointerdown", _this.handlePointerDown);
+ hitDragging.emitter.on("dragstart", _this.handleDragStart);
+ hitDragging.emitter.on("hitupdate", _this.handleHitUpdate);
+ hitDragging.emitter.on("dragend", _this.handleDragEnd);
+ return _this;
+ }
+ EventResizing.prototype.destroy = function() {
+ this.dragging.destroy();
+ };
+ EventResizing.prototype.querySegEl = function(ev) {
+ return elementClosest(ev.subjectEl, ".fc-event");
+ };
+ return EventResizing;
+ })(Interaction);
+ function computeMutation(hit0, hit1, isFromStart, instanceRange) {
+ var dateEnv = hit0.context.dateEnv;
+ var date0 = hit0.dateSpan.range.start;
+ var date1 = hit1.dateSpan.range.start;
+ var delta = diffDates(date0, date1, dateEnv, hit0.largeUnit);
+ if (isFromStart) {
+ if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
+ return { startDelta: delta };
+ }
+ } else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
+ return { endDelta: delta };
+ }
+ return null;
+ }
+
+ var UnselectAuto = /** @class */ (function() {
+ function UnselectAuto(context) {
+ var _this = this;
+ this.context = context;
+ this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
+ this.matchesCancel = false;
+ this.matchesEvent = false;
+ this.onSelect = function(selectInfo) {
+ if (selectInfo.jsEvent) {
+ _this.isRecentPointerDateSelect = true;
+ }
+ };
+ this.onDocumentPointerDown = function(pev) {
+ var unselectCancel = _this.context.options.unselectCancel;
+ var downEl = getEventTargetViaRoot(pev.origEvent);
+ _this.matchesCancel = !!elementClosest(downEl, unselectCancel);
+ _this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
+ };
+ this.onDocumentPointerUp = function(pev) {
+ var context = _this.context;
+ var documentPointer = _this.documentPointer;
+ var calendarState = context.getCurrentData();
+ // touch-scrolling should never unfocus any type of selection
+ if (!documentPointer.wasTouchScroll) {
+ if (
+ calendarState.dateSelection && // an existing date selection?
+ !_this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
+ ) {
+ var unselectAuto = context.options.unselectAuto;
+ if (unselectAuto && (!unselectAuto || !_this.matchesCancel)) {
+ context.calendarApi.unselect(pev);
+ }
+ }
+ if (
+ calendarState.eventSelection && // an existing event selected?
+ !_this.matchesEvent // interaction DIDN'T start on an event
+ ) {
+ context.dispatch({ type: "UNSELECT_EVENT" });
+ }
+ }
+ _this.isRecentPointerDateSelect = false;
+ };
+ var documentPointer = (this.documentPointer = new PointerDragging(
+ document
+ ));
+ documentPointer.shouldIgnoreMove = true;
+ documentPointer.shouldWatchScroll = false;
+ documentPointer.emitter.on("pointerdown", this.onDocumentPointerDown);
+ documentPointer.emitter.on("pointerup", this.onDocumentPointerUp);
+ /*
+ TODO: better way to know about whether there was a selection with the pointer
+ */
+ context.emitter.on("select", this.onSelect);
+ }
+ UnselectAuto.prototype.destroy = function() {
+ this.context.emitter.off("select", this.onSelect);
+ this.documentPointer.destroy();
+ };
+ return UnselectAuto;
+ })();
+
+ var OPTION_REFINERS$3 = {
+ fixedMirrorParent: identity
+ };
+ var LISTENER_REFINERS = {
+ dateClick: identity,
+ eventDragStart: identity,
+ eventDragStop: identity,
+ eventDrop: identity,
+ eventResizeStart: identity,
+ eventResizeStop: identity,
+ eventResize: identity,
+ drop: identity,
+ eventReceive: identity,
+ eventLeave: identity
+ };
+
+ /*
+ Given an already instantiated draggable object for one-or-more elements,
+ Interprets any dragging as an attempt to drag an events that lives outside
+ of a calendar onto a calendar.
+ */
+ var ExternalElementDragging = /** @class */ (function() {
+ function ExternalElementDragging(dragging, suppliedDragMeta) {
+ var _this = this;
+ this.receivingContext = null;
+ this.droppableEvent = null; // will exist for all drags, even if create:false
+ this.suppliedDragMeta = null;
+ this.dragMeta = null;
+ this.handleDragStart = function(ev) {
+ _this.dragMeta = _this.buildDragMeta(ev.subjectEl);
+ };
+ this.handleHitUpdate = function(hit, isFinal, ev) {
+ var dragging = _this.hitDragging.dragging;
+ var receivingContext = null;
+ var droppableEvent = null;
+ var isInvalid = false;
+ var interaction = {
+ affectedEvents: createEmptyEventStore(),
+ mutatedEvents: createEmptyEventStore(),
+ isEvent: _this.dragMeta.create
+ };
+ if (hit) {
+ receivingContext = hit.context;
+ if (_this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
+ droppableEvent = computeEventForDateSpan(
+ hit.dateSpan,
+ _this.dragMeta,
+ receivingContext
+ );
+ interaction.mutatedEvents = eventTupleToStore(droppableEvent);
+ isInvalid = !isInteractionValid(
+ interaction,
+ hit.dateProfile,
+ receivingContext
+ );
+ if (isInvalid) {
+ interaction.mutatedEvents = createEmptyEventStore();
+ droppableEvent = null;
+ }
+ }
+ }
+ _this.displayDrag(receivingContext, interaction);
+ // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
+ // TODO: wish we could somehow wait for dispatch to guarantee render
+ dragging.setMirrorIsVisible(
+ isFinal ||
+ !droppableEvent ||
+ !document.querySelector(".fc-event-mirror")
+ );
+ if (!isInvalid) {
+ enableCursor();
+ } else {
+ disableCursor();
+ }
+ if (!isFinal) {
+ dragging.setMirrorNeedsRevert(!droppableEvent);
+ _this.receivingContext = receivingContext;
+ _this.droppableEvent = droppableEvent;
+ }
+ };
+ this.handleDragEnd = function(pev) {
+ var _a = _this,
+ receivingContext = _a.receivingContext,
+ droppableEvent = _a.droppableEvent;
+ _this.clearDrag();
+ if (receivingContext && droppableEvent) {
+ var finalHit = _this.hitDragging.finalHit;
+ var finalView = finalHit.context.viewApi;
+ var dragMeta = _this.dragMeta;
+ receivingContext.emitter.trigger(
+ "drop",
+ __assign(
+ __assign(
+ {},
+ buildDatePointApiWithContext(
+ finalHit.dateSpan,
+ receivingContext
+ )
+ ),
+ {
+ draggedEl: pev.subjectEl,
+ jsEvent: pev.origEvent,
+ view: finalView
+ }
+ )
+ );
+ if (dragMeta.create) {
+ var addingEvents_1 = eventTupleToStore(droppableEvent);
+ receivingContext.dispatch({
+ type: "MERGE_EVENTS",
+ eventStore: addingEvents_1
+ });
+ if (pev.isTouch) {
+ receivingContext.dispatch({
+ type: "SELECT_EVENT",
+ eventInstanceId: droppableEvent.instance.instanceId
+ });
+ }
+ // signal that an external event landed
+ receivingContext.emitter.trigger("eventReceive", {
+ event: new EventApi(
+ receivingContext,
+ droppableEvent.def,
+ droppableEvent.instance
+ ),
+ relatedEvents: [],
+ revert: function() {
+ receivingContext.dispatch({
+ type: "REMOVE_EVENTS",
+ eventStore: addingEvents_1
+ });
+ },
+ draggedEl: pev.subjectEl,
+ view: finalView
+ });
+ }
+ }
+ _this.receivingContext = null;
+ _this.droppableEvent = null;
+ };
+ var hitDragging = (this.hitDragging = new HitDragging(
+ dragging,
+ interactionSettingsStore
+ ));
+ hitDragging.requireInitial = false; // will start outside of a component
+ hitDragging.emitter.on("dragstart", this.handleDragStart);
+ hitDragging.emitter.on("hitupdate", this.handleHitUpdate);
+ hitDragging.emitter.on("dragend", this.handleDragEnd);
+ this.suppliedDragMeta = suppliedDragMeta;
+ }
+ ExternalElementDragging.prototype.buildDragMeta = function(subjectEl) {
+ if (typeof this.suppliedDragMeta === "object") {
+ return parseDragMeta(this.suppliedDragMeta);
+ }
+ if (typeof this.suppliedDragMeta === "function") {
+ return parseDragMeta(this.suppliedDragMeta(subjectEl));
+ }
+ return getDragMetaFromEl(subjectEl);
+ };
+ ExternalElementDragging.prototype.displayDrag = function(
+ nextContext,
+ state
+ ) {
+ var prevContext = this.receivingContext;
+ if (prevContext && prevContext !== nextContext) {
+ prevContext.dispatch({ type: "UNSET_EVENT_DRAG" });
+ }
+ if (nextContext) {
+ nextContext.dispatch({ type: "SET_EVENT_DRAG", state: state });
+ }
+ };
+ ExternalElementDragging.prototype.clearDrag = function() {
+ if (this.receivingContext) {
+ this.receivingContext.dispatch({ type: "UNSET_EVENT_DRAG" });
+ }
+ };
+ ExternalElementDragging.prototype.canDropElOnCalendar = function(
+ el,
+ receivingContext
+ ) {
+ var dropAccept = receivingContext.options.dropAccept;
+ if (typeof dropAccept === "function") {
+ return dropAccept.call(receivingContext.calendarApi, el);
+ }
+ if (typeof dropAccept === "string" && dropAccept) {
+ return Boolean(elementMatches(el, dropAccept));
+ }
+ return true;
+ };
+ return ExternalElementDragging;
+ })();
+ // Utils for computing event store from the DragMeta
+ // ----------------------------------------------------------------------------------------------------
+ function computeEventForDateSpan(dateSpan, dragMeta, context) {
+ var defProps = __assign({}, dragMeta.leftoverProps);
+ for (
+ var _i = 0, _a = context.pluginHooks.externalDefTransforms;
+ _i < _a.length;
+ _i++
+ ) {
+ var transform = _a[_i];
+ __assign(defProps, transform(dateSpan, dragMeta));
+ }
+ var _b = refineEventDef(defProps, context),
+ refined = _b.refined,
+ extra = _b.extra;
+ var def = parseEventDef(
+ refined,
+ extra,
+ dragMeta.sourceId,
+ dateSpan.allDay,
+ context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
+ context
+ );
+ var start = dateSpan.range.start;
+ // only rely on time info if drop zone is all-day,
+ // otherwise, we already know the time
+ if (dateSpan.allDay && dragMeta.startTime) {
+ start = context.dateEnv.add(start, dragMeta.startTime);
+ }
+ var end = dragMeta.duration
+ ? context.dateEnv.add(start, dragMeta.duration)
+ : getDefaultEventEnd(dateSpan.allDay, start, context);
+ var instance = createEventInstance(def.defId, { start: start, end: end });
+ return { def: def, instance: instance };
+ }
+ // Utils for extracting data from element
+ // ----------------------------------------------------------------------------------------------------
+ function getDragMetaFromEl(el) {
+ var str = getEmbeddedElData(el, "event");
+ var obj = str ? JSON.parse(str) : { create: false }; // if no embedded data, assume no event creation
+ return parseDragMeta(obj);
+ }
+ config.dataAttrPrefix = "";
+ function getEmbeddedElData(el, name) {
+ var prefix = config.dataAttrPrefix;
+ var prefixedName = (prefix ? prefix + "-" : "") + name;
+ return el.getAttribute("data-" + prefixedName) || "";
+ }
+
+ /*
+ Makes an element (that is *external* to any calendar) draggable.
+ Can pass in data that determines how an event will be created when dropped onto a calendar.
+ Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
+ */
+ var ExternalDraggable = /** @class */ (function() {
+ function ExternalDraggable(el, settings) {
+ var _this = this;
+ if (settings === void 0) {
+ settings = {};
+ }
+ this.handlePointerDown = function(ev) {
+ var dragging = _this.dragging;
+ var _a = _this.settings,
+ minDistance = _a.minDistance,
+ longPressDelay = _a.longPressDelay;
+ dragging.minDistance =
+ minDistance != null
+ ? minDistance
+ : ev.isTouch
+ ? 0
+ : BASE_OPTION_DEFAULTS.eventDragMinDistance;
+ dragging.delay = ev.isTouch // TODO: eventually read eventLongPressDelay instead vvv
+ ? longPressDelay != null
+ ? longPressDelay
+ : BASE_OPTION_DEFAULTS.longPressDelay
+ : 0;
+ };
+ this.handleDragStart = function(ev) {
+ if (
+ ev.isTouch &&
+ _this.dragging.delay &&
+ ev.subjectEl.classList.contains("fc-event")
+ ) {
+ _this.dragging.mirror
+ .getMirrorEl()
+ .classList.add("fc-event-selected");
+ }
+ };
+ this.settings = settings;
+ var dragging = (this.dragging = new FeaturefulElementDragging(el));
+ dragging.touchScrollAllowed = false;
+ if (settings.itemSelector != null) {
+ dragging.pointer.selector = settings.itemSelector;
+ }
+ if (settings.appendTo != null) {
+ dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
+ }
+ dragging.emitter.on("pointerdown", this.handlePointerDown);
+ dragging.emitter.on("dragstart", this.handleDragStart);
+ new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
+ }
+ ExternalDraggable.prototype.destroy = function() {
+ this.dragging.destroy();
+ };
+ return ExternalDraggable;
+ })();
+
+ /*
+ Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
+ The third-party system is responsible for drawing the visuals effects of the drag.
+ This class simply monitors for pointer movements and fires events.
+ It also has the ability to hide the moving element (the "mirror") during the drag.
+ */
+ var InferredElementDragging = /** @class */ (function(_super) {
+ __extends(InferredElementDragging, _super);
+ function InferredElementDragging(containerEl) {
+ var _this = _super.call(this, containerEl) || this;
+ _this.shouldIgnoreMove = false;
+ _this.mirrorSelector = "";
+ _this.currentMirrorEl = null;
+ _this.handlePointerDown = function(ev) {
+ _this.emitter.trigger("pointerdown", ev);
+ if (!_this.shouldIgnoreMove) {
+ // fire dragstart right away. does not support delay or min-distance
+ _this.emitter.trigger("dragstart", ev);
+ }
+ };
+ _this.handlePointerMove = function(ev) {
+ if (!_this.shouldIgnoreMove) {
+ _this.emitter.trigger("dragmove", ev);
+ }
+ };
+ _this.handlePointerUp = function(ev) {
+ _this.emitter.trigger("pointerup", ev);
+ if (!_this.shouldIgnoreMove) {
+ // fire dragend right away. does not support a revert animation
+ _this.emitter.trigger("dragend", ev);
+ }
+ };
+ var pointer = (_this.pointer = new PointerDragging(containerEl));
+ pointer.emitter.on("pointerdown", _this.handlePointerDown);
+ pointer.emitter.on("pointermove", _this.handlePointerMove);
+ pointer.emitter.on("pointerup", _this.handlePointerUp);
+ return _this;
+ }
+ InferredElementDragging.prototype.destroy = function() {
+ this.pointer.destroy();
+ };
+ InferredElementDragging.prototype.setIgnoreMove = function(bool) {
+ this.shouldIgnoreMove = bool;
+ };
+ InferredElementDragging.prototype.setMirrorIsVisible = function(bool) {
+ if (bool) {
+ // restore a previously hidden element.
+ // use the reference in case the selector class has already been removed.
+ if (this.currentMirrorEl) {
+ this.currentMirrorEl.style.visibility = "";
+ this.currentMirrorEl = null;
+ }
+ } else {
+ var mirrorEl = this.mirrorSelector
+ ? // TODO: somehow query FullCalendars WITHIN shadow-roots
+ document.querySelector(this.mirrorSelector)
+ : null;
+ if (mirrorEl) {
+ this.currentMirrorEl = mirrorEl;
+ mirrorEl.style.visibility = "hidden";
+ }
+ }
+ };
+ return InferredElementDragging;
+ })(ElementDragging);
+
+ /*
+ Bridges third-party drag-n-drop systems with FullCalendar.
+ Must be instantiated and destroyed by caller.
+ */
+ var ThirdPartyDraggable = /** @class */ (function() {
+ function ThirdPartyDraggable(containerOrSettings, settings) {
+ var containerEl = document;
+ if (
+ // wish we could just test instanceof EventTarget, but doesn't work in IE11
+ containerOrSettings === document ||
+ containerOrSettings instanceof Element
+ ) {
+ containerEl = containerOrSettings;
+ settings = settings || {};
+ } else {
+ settings = containerOrSettings || {};
+ }
+ var dragging = (this.dragging = new InferredElementDragging(containerEl));
+ if (typeof settings.itemSelector === "string") {
+ dragging.pointer.selector = settings.itemSelector;
+ } else if (containerEl === document) {
+ dragging.pointer.selector = "[data-event]";
+ }
+ if (typeof settings.mirrorSelector === "string") {
+ dragging.mirrorSelector = settings.mirrorSelector;
+ }
+ new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
+ }
+ ThirdPartyDraggable.prototype.destroy = function() {
+ this.dragging.destroy();
+ };
+ return ThirdPartyDraggable;
+ })();
+
+ var interactionPlugin = createPlugin({
+ componentInteractions: [
+ DateClicking,
+ DateSelecting,
+ EventDragging,
+ EventResizing
+ ],
+ calendarInteractions: [UnselectAuto],
+ elementDraggingImpl: FeaturefulElementDragging,
+ optionRefiners: OPTION_REFINERS$3,
+ listenerRefiners: LISTENER_REFINERS
+ });
+
+ /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // It is a manager for a Table subcomponent, which does most of the heavy lifting.
+ // It is responsible for managing width/height.
+ var TableView = /** @class */ (function(_super) {
+ __extends(TableView, _super);
+ function TableView() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.headerElRef = createRef();
+ return _this;
+ }
+ TableView.prototype.renderSimpleLayout = function(
+ headerRowContent,
+ bodyContent
+ ) {
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var sections = [];
+ var stickyHeaderDates = getStickyHeaderDates(context.options);
+ if (headerRowContent) {
+ sections.push({
+ type: "header",
+ key: "header",
+ isSticky: stickyHeaderDates,
+ chunk: {
+ elRef: this.headerElRef,
+ tableClassName: "fc-col-header",
+ rowContent: headerRowContent
+ }
+ });
+ }
+ sections.push({
+ type: "body",
+ key: "body",
+ liquid: true,
+ chunk: { content: bodyContent }
+ });
+ return createElement(ViewRoot, { viewSpec: context.viewSpec }, function(
+ rootElRef,
+ classNames
+ ) {
+ return createElement(
+ "div",
+ {
+ ref: rootElRef,
+ className: ["fc-daygrid"].concat(classNames).join(" ")
+ },
+ createElement(SimpleScrollGrid, {
+ liquid: !props.isHeightAuto && !props.forPrint,
+ collapsibleWidth: props.forPrint,
+ cols: [] /* TODO: make optional? */,
+ sections: sections
+ })
+ );
+ });
+ };
+ TableView.prototype.renderHScrollLayout = function(
+ headerRowContent,
+ bodyContent,
+ colCnt,
+ dayMinWidth
+ ) {
+ var ScrollGrid = this.context.pluginHooks.scrollGridImpl;
+ if (!ScrollGrid) {
+ throw new Error("No ScrollGrid implementation");
+ }
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var stickyHeaderDates =
+ !props.forPrint && getStickyHeaderDates(context.options);
+ var stickyFooterScrollbar =
+ !props.forPrint && getStickyFooterScrollbar(context.options);
+ var sections = [];
+ if (headerRowContent) {
+ sections.push({
+ type: "header",
+ key: "header",
+ isSticky: stickyHeaderDates,
+ chunks: [
+ {
+ key: "main",
+ elRef: this.headerElRef,
+ tableClassName: "fc-col-header",
+ rowContent: headerRowContent
+ }
+ ]
+ });
+ }
+ sections.push({
+ type: "body",
+ key: "body",
+ liquid: true,
+ chunks: [
+ {
+ key: "main",
+ content: bodyContent
+ }
+ ]
+ });
+ if (stickyFooterScrollbar) {
+ sections.push({
+ type: "footer",
+ key: "footer",
+ isSticky: true,
+ chunks: [
+ {
+ key: "main",
+ content: renderScrollShim
+ }
+ ]
+ });
+ }
+ return createElement(ViewRoot, { viewSpec: context.viewSpec }, function(
+ rootElRef,
+ classNames
+ ) {
+ return createElement(
+ "div",
+ {
+ ref: rootElRef,
+ className: ["fc-daygrid"].concat(classNames).join(" ")
+ },
+ createElement(ScrollGrid, {
+ liquid: !props.isHeightAuto && !props.forPrint,
+ collapsibleWidth: props.forPrint,
+ colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }],
+ sections: sections
+ })
+ );
+ });
+ };
+ return TableView;
+ })(DateComponent);
+
+ function splitSegsByRow(segs, rowCnt) {
+ var byRow = [];
+ for (var i = 0; i < rowCnt; i += 1) {
+ byRow[i] = [];
+ }
+ for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
+ var seg = segs_1[_i];
+ byRow[seg.row].push(seg);
+ }
+ return byRow;
+ }
+ function splitSegsByFirstCol(segs, colCnt) {
+ var byCol = [];
+ for (var i = 0; i < colCnt; i += 1) {
+ byCol[i] = [];
+ }
+ for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
+ var seg = segs_2[_i];
+ byCol[seg.firstCol].push(seg);
+ }
+ return byCol;
+ }
+ function splitInteractionByRow(ui, rowCnt) {
+ var byRow = [];
+ if (!ui) {
+ for (var i = 0; i < rowCnt; i += 1) {
+ byRow[i] = null;
+ }
+ } else {
+ for (var i = 0; i < rowCnt; i += 1) {
+ byRow[i] = {
+ affectedInstances: ui.affectedInstances,
+ isEvent: ui.isEvent,
+ segs: []
+ };
+ }
+ for (var _i = 0, _a = ui.segs; _i < _a.length; _i++) {
+ var seg = _a[_i];
+ byRow[seg.row].segs.push(seg);
+ }
+ }
+ return byRow;
+ }
+
+ var TableCellTop = /** @class */ (function(_super) {
+ __extends(TableCellTop, _super);
+ function TableCellTop() {
+ return (_super !== null && _super.apply(this, arguments)) || this;
+ }
+ TableCellTop.prototype.render = function() {
+ var props = this.props;
+ var navLinkAttrs = buildNavLinkAttrs(this.context, props.date);
+ return createElement(
+ DayCellContent,
+ {
+ date: props.date,
+ dateProfile: props.dateProfile,
+ todayRange: props.todayRange,
+ showDayNumber: props.showDayNumber,
+ extraHookProps: props.extraHookProps,
+ defaultContent: renderTopInner
+ },
+ function(innerElRef, innerContent) {
+ return (
+ (innerContent || props.forceDayTop) &&
+ createElement(
+ "div",
+ { className: "fc-daygrid-day-top", ref: innerElRef },
+ createElement(
+ "a",
+ __assign(
+ { id: props.dayNumberId, className: "fc-daygrid-day-number" },
+ navLinkAttrs
+ ),
+ innerContent || createElement(Fragment, null, "\u00A0")
+ )
+ )
+ );
+ }
+ );
+ };
+ return TableCellTop;
+ })(BaseComponent);
+ function renderTopInner(props) {
+ return props.dayNumberText;
+ }
+
+ var DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
+ hour: "numeric",
+ minute: "2-digit",
+ omitZeroMinute: true,
+ meridiem: "narrow"
+ });
+ function hasListItemDisplay(seg) {
+ var display = seg.eventRange.ui.display;
+ return (
+ display === "list-item" ||
+ (display === "auto" &&
+ !seg.eventRange.def.allDay &&
+ seg.firstCol === seg.lastCol && // can't be multi-day
+ seg.isStart && // "
+ seg.isEnd) // "
+ );
+ }
+
+ var TableBlockEvent = /** @class */ (function(_super) {
+ __extends(TableBlockEvent, _super);
+ function TableBlockEvent() {
+ return (_super !== null && _super.apply(this, arguments)) || this;
+ }
+ TableBlockEvent.prototype.render = function() {
+ var props = this.props;
+ return createElement(
+ StandardEvent,
+ __assign({}, props, {
+ extraClassNames: [
+ "fc-daygrid-event",
+ "fc-daygrid-block-event",
+ "fc-h-event"
+ ],
+ defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT,
+ defaultDisplayEventEnd: props.defaultDisplayEventEnd,
+ disableResizing: !props.seg.eventRange.def.allDay
+ })
+ );
+ };
+ return TableBlockEvent;
+ })(BaseComponent);
+
+ var TableListItemEvent = /** @class */ (function(_super) {
+ __extends(TableListItemEvent, _super);
+ function TableListItemEvent() {
+ return (_super !== null && _super.apply(this, arguments)) || this;
+ }
+ TableListItemEvent.prototype.render = function() {
+ var _a = this,
+ props = _a.props,
+ context = _a.context;
+ var timeFormat =
+ context.options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
+ var timeText = buildSegTimeText(
+ props.seg,
+ timeFormat,
+ context,
+ true,
+ props.defaultDisplayEventEnd
+ );
+ return createElement(
+ EventRoot,
+ {
+ seg: props.seg,
+ timeText: timeText,
+ defaultContent: renderInnerContent$2,
+ isDragging: props.isDragging,
+ isResizing: false,
+ isDateSelecting: false,
+ isSelected: props.isSelected,
+ isPast: props.isPast,
+ isFuture: props.isFuture,
+ isToday: props.isToday
+ },
+ function(rootElRef, classNames, innerElRef, innerContent) {
+ return (
+ // we don't use styles!
+ createElement(
+ "a",
+ __assign(
+ {
+ className: ["fc-daygrid-event", "fc-daygrid-dot-event"]
+ .concat(classNames)
+ .join(" "),
+ ref: rootElRef
+ },
+ getSegAnchorAttrs(props.seg, context)
+ ),
+ innerContent
+ )
+ );
+ }
+ );
+ };
+ return TableListItemEvent;
+ })(BaseComponent);
+ function renderInnerContent$2(innerProps) {
+ return createElement(
+ Fragment,
+ null,
+ createElement("div", {
+ className: "fc-daygrid-event-dot",
+ style: {
+ borderColor: innerProps.borderColor || innerProps.backgroundColor
+ }
+ }),
+ innerProps.timeText &&
+ createElement(
+ "div",
+ { className: "fc-event-time" },
+ innerProps.timeText
+ ),
+ createElement(
+ "div",
+ { className: "fc-event-title" },
+ innerProps.event.title || createElement(Fragment, null, "\u00A0")
+ )
+ );
+ }
+
+ var TableCellMoreLink = /** @class */ (function(_super) {
+ __extends(TableCellMoreLink, _super);
+ function TableCellMoreLink() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.compileSegs = memoize(compileSegs);
+ return _this;
+ }
+ TableCellMoreLink.prototype.render = function() {
+ var props = this.props;
+ var _a = this.compileSegs(props.singlePlacements),
+ allSegs = _a.allSegs,
+ invisibleSegs = _a.invisibleSegs;
+ return createElement(
+ MoreLinkRoot,
+ {
+ dateProfile: props.dateProfile,
+ todayRange: props.todayRange,
+ allDayDate: props.allDayDate,
+ moreCnt: props.moreCnt,
+ allSegs: allSegs,
+ hiddenSegs: invisibleSegs,
+ alignmentElRef: props.alignmentElRef,
+ alignGridTop: props.alignGridTop,
+ extraDateSpan: props.extraDateSpan,
+ popoverContent: function() {
+ var isForcedInvisible =
+ (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
+ (props.eventResize
+ ? props.eventResize.affectedInstances
+ : null) ||
+ {};
+ return createElement(
+ Fragment,
+ null,
+ allSegs.map(function(seg) {
+ var instanceId = seg.eventRange.instance.instanceId;
+ return createElement(
+ "div",
+ {
+ className: "fc-daygrid-event-harness",
+ key: instanceId,
+ style: {
+ visibility: isForcedInvisible[instanceId] ? "hidden" : ""
+ }
+ },
+ hasListItemDisplay(seg)
+ ? createElement(
+ TableListItemEvent,
+ __assign(
+ {
+ seg: seg,
+ isDragging: false,
+ isSelected: instanceId === props.eventSelection,
+ defaultDisplayEventEnd: false
+ },
+ getSegMeta(seg, props.todayRange)
+ )
+ )
+ : createElement(
+ TableBlockEvent,
+ __assign(
+ {
+ seg: seg,
+ isDragging: false,
+ isResizing: false,
+ isDateSelecting: false,
+ isSelected: instanceId === props.eventSelection,
+ defaultDisplayEventEnd: false
+ },
+ getSegMeta(seg, props.todayRange)
+ )
+ )
+ );
+ })
+ );
+ }
+ },
+ function(
+ rootElRef,
+ classNames,
+ innerElRef,
+ innerContent,
+ handleClick,
+ title,
+ isExpanded,
+ popoverId
+ ) {
+ return createElement(
+ "a",
+ __assign(
+ {
+ ref: rootElRef,
+ className: ["fc-daygrid-more-link"]
+ .concat(classNames)
+ .join(" "),
+ title: title,
+ "aria-expanded": isExpanded,
+ "aria-controls": popoverId
+ },
+ createAriaClickAttrs(handleClick)
+ ),
+ innerContent
+ );
+ }
+ );
+ };
+ return TableCellMoreLink;
+ })(BaseComponent);
+ function compileSegs(singlePlacements) {
+ var allSegs = [];
+ var invisibleSegs = [];
+ for (
+ var _i = 0, singlePlacements_1 = singlePlacements;
+ _i < singlePlacements_1.length;
+ _i++
+ ) {
+ var placement = singlePlacements_1[_i];
+ allSegs.push(placement.seg);
+ if (!placement.isVisible) {
+ invisibleSegs.push(placement.seg);
+ }
+ }
+ return { allSegs: allSegs, invisibleSegs: invisibleSegs };
+ }
+
+ var DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: "narrow" });
+ var TableCell = /** @class */ (function(_super) {
+ __extends(TableCell, _super);
+ function TableCell() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.rootElRef = createRef();
+ _this.state = {
+ dayNumberId: getUniqueDomId()
+ };
+ _this.handleRootEl = function(el) {
+ setRef(_this.rootElRef, el);
+ setRef(_this.props.elRef, el);
+ };
+ return _this;
+ }
+ TableCell.prototype.render = function() {
+ var _a = this,
+ context = _a.context,
+ props = _a.props,
+ state = _a.state,
+ rootElRef = _a.rootElRef;
+ var date = props.date,
+ dateProfile = props.dateProfile;
+ var navLinkAttrs = buildNavLinkAttrs(context, date, "week");
+ return createElement(
+ DayCellRoot,
+ {
+ date: date,
+ dateProfile: dateProfile,
+ todayRange: props.todayRange,
+ showDayNumber: props.showDayNumber,
+ extraHookProps: props.extraHookProps,
+ elRef: this.handleRootEl
+ },
+ function(dayElRef, dayClassNames, rootDataAttrs, isDisabled) {
+ return createElement(
+ "td",
+ __assign(
+ {
+ ref: dayElRef,
+ role: "gridcell",
+ className: ["fc-daygrid-day"]
+ .concat(dayClassNames, props.extraClassNames || [])
+ .join(" ")
+ },
+ rootDataAttrs,
+ props.extraDataAttrs,
+ props.showDayNumber
+ ? { "aria-labelledby": state.dayNumberId }
+ : {}
+ ),
+ createElement(
+ "div",
+ {
+ className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner",
+ ref: props.innerElRef /* different from hook system! RENAME */
+ },
+ props.showWeekNumber &&
+ createElement(
+ WeekNumberRoot,
+ { date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 },
+ function(
+ weekElRef,
+ weekClassNames,
+ innerElRef,
+ innerContent
+ ) {
+ return createElement(
+ "a",
+ __assign(
+ {
+ ref: weekElRef,
+ className: ["fc-daygrid-week-number"]
+ .concat(weekClassNames)
+ .join(" ")
+ },
+ navLinkAttrs
+ ),
+ innerContent
+ );
+ }
+ ),
+ !isDisabled &&
+ createElement(TableCellTop, {
+ date: date,
+ dateProfile: dateProfile,
+ showDayNumber: props.showDayNumber,
+ dayNumberId: state.dayNumberId,
+ forceDayTop: props.forceDayTop,
+ todayRange: props.todayRange,
+ extraHookProps: props.extraHookProps
+ }),
+ createElement(
+ "div",
+ {
+ className: "fc-daygrid-day-events",
+ ref: props.fgContentElRef
+ },
+ props.fgContent,
+ createElement(
+ "div",
+ {
+ className: "fc-daygrid-day-bottom",
+ style: { marginTop: props.moreMarginTop }
+ },
+ createElement(TableCellMoreLink, {
+ allDayDate: date,
+ singlePlacements: props.singlePlacements,
+ moreCnt: props.moreCnt,
+ alignmentElRef: rootElRef,
+ alignGridTop: !props.showDayNumber,
+ extraDateSpan: props.extraDateSpan,
+ dateProfile: props.dateProfile,
+ eventSelection: props.eventSelection,
+ eventDrag: props.eventDrag,
+ eventResize: props.eventResize,
+ todayRange: props.todayRange
+ })
+ )
+ ),
+ createElement(
+ "div",
+ { className: "fc-daygrid-day-bg" },
+ props.bgContent
+ )
+ )
+ );
+ }
+ );
+ };
+ return TableCell;
+ })(DateComponent);
+
+ function computeFgSegPlacement(
+ segs, // assumed already sorted
+ dayMaxEvents,
+ dayMaxEventRows,
+ strictOrder,
+ eventInstanceHeights,
+ maxContentHeight,
+ cells
+ ) {
+ var hierarchy = new DayGridSegHierarchy();
+ hierarchy.allowReslicing = true;
+ hierarchy.strictOrder = strictOrder;
+ if (dayMaxEvents === true || dayMaxEventRows === true) {
+ hierarchy.maxCoord = maxContentHeight;
+ hierarchy.hiddenConsumes = true;
+ } else if (typeof dayMaxEvents === "number") {
+ hierarchy.maxStackCnt = dayMaxEvents;
+ } else if (typeof dayMaxEventRows === "number") {
+ hierarchy.maxStackCnt = dayMaxEventRows;
+ hierarchy.hiddenConsumes = true;
+ }
+ // create segInputs only for segs with known heights
+ var segInputs = [];
+ var unknownHeightSegs = [];
+ for (var i = 0; i < segs.length; i += 1) {
+ var seg = segs[i];
+ var instanceId = seg.eventRange.instance.instanceId;
+ var eventHeight = eventInstanceHeights[instanceId];
+ if (eventHeight != null) {
+ segInputs.push({
+ index: i,
+ thickness: eventHeight,
+ span: {
+ start: seg.firstCol,
+ end: seg.lastCol + 1
+ }
+ });
+ } else {
+ unknownHeightSegs.push(seg);
+ }
+ }
+ var hiddenEntries = hierarchy.addSegs(segInputs);
+ var segRects = hierarchy.toRects();
+ var _a = placeRects(segRects, segs, cells),
+ singleColPlacements = _a.singleColPlacements,
+ multiColPlacements = _a.multiColPlacements,
+ leftoverMargins = _a.leftoverMargins;
+ var moreCnts = [];
+ var moreMarginTops = [];
+ // add segs with unknown heights
+ for (
+ var _i = 0, unknownHeightSegs_1 = unknownHeightSegs;
+ _i < unknownHeightSegs_1.length;
+ _i++
+ ) {
+ var seg = unknownHeightSegs_1[_i];
+ multiColPlacements[seg.firstCol].push({
+ seg: seg,
+ isVisible: false,
+ isAbsolute: true,
+ absoluteTop: 0,
+ marginTop: 0
+ });
+ for (var col = seg.firstCol; col <= seg.lastCol; col += 1) {
+ singleColPlacements[col].push({
+ seg: resliceSeg(seg, col, col + 1, cells),
+ isVisible: false,
+ isAbsolute: false,
+ absoluteTop: 0,
+ marginTop: 0
+ });
+ }
+ }
+ // add the hidden entries
+ for (var col = 0; col < cells.length; col += 1) {
+ moreCnts.push(0);
+ }
+ for (
+ var _b = 0, hiddenEntries_1 = hiddenEntries;
+ _b < hiddenEntries_1.length;
+ _b++
+ ) {
+ var hiddenEntry = hiddenEntries_1[_b];
+ var seg = segs[hiddenEntry.index];
+ var hiddenSpan = hiddenEntry.span;
+ multiColPlacements[hiddenSpan.start].push({
+ seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
+ isVisible: false,
+ isAbsolute: true,
+ absoluteTop: 0,
+ marginTop: 0
+ });
+ for (var col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
+ moreCnts[col] += 1;
+ singleColPlacements[col].push({
+ seg: resliceSeg(seg, col, col + 1, cells),
+ isVisible: false,
+ isAbsolute: false,
+ absoluteTop: 0,
+ marginTop: 0
+ });
+ }
+ }
+ // deal with leftover margins
+ for (var col = 0; col < cells.length; col += 1) {
+ moreMarginTops.push(leftoverMargins[col]);
+ }
+ return {
+ singleColPlacements: singleColPlacements,
+ multiColPlacements: multiColPlacements,
+ moreCnts: moreCnts,
+ moreMarginTops: moreMarginTops
+ };
+ }
+ // rects ordered by top coord, then left
+ function placeRects(allRects, segs, cells) {
+ var rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
+ var singleColPlacements = [];
+ var multiColPlacements = [];
+ var leftoverMargins = [];
+ for (var col = 0; col < cells.length; col += 1) {
+ var rects = rectsByEachCol[col];
+ // compute all static segs in singlePlacements
+ var singlePlacements = [];
+ var currentHeight = 0;
+ var currentMarginTop = 0;
+ for (var _i = 0, rects_1 = rects; _i < rects_1.length; _i++) {
+ var rect = rects_1[_i];
+ var seg = segs[rect.index];
+ singlePlacements.push({
+ seg: resliceSeg(seg, col, col + 1, cells),
+ isVisible: true,
+ isAbsolute: false,
+ absoluteTop: rect.levelCoord,
+ marginTop: rect.levelCoord - currentHeight
+ });
+ currentHeight = rect.levelCoord + rect.thickness;
+ }
+ // compute mixed static/absolute segs in multiPlacements
+ var multiPlacements = [];
+ currentHeight = 0;
+ currentMarginTop = 0;
+ for (var _a = 0, rects_2 = rects; _a < rects_2.length; _a++) {
+ var rect = rects_2[_a];
+ var seg = segs[rect.index];
+ var isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
+ var isFirstCol = rect.span.start === col;
+ currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
+ currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
+ if (isAbsolute) {
+ currentMarginTop += rect.thickness;
+ if (isFirstCol) {
+ multiPlacements.push({
+ seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
+ isVisible: true,
+ isAbsolute: true,
+ absoluteTop: rect.levelCoord,
+ marginTop: 0
+ });
+ }
+ } else if (isFirstCol) {
+ multiPlacements.push({
+ seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
+ isVisible: true,
+ isAbsolute: false,
+ absoluteTop: rect.levelCoord,
+ marginTop: currentMarginTop // claim the margin
+ });
+ currentMarginTop = 0;
+ }
+ }
+ singleColPlacements.push(singlePlacements);
+ multiColPlacements.push(multiPlacements);
+ leftoverMargins.push(currentMarginTop);
+ }
+ return {
+ singleColPlacements: singleColPlacements,
+ multiColPlacements: multiColPlacements,
+ leftoverMargins: leftoverMargins
+ };
+ }
+ function groupRectsByEachCol(rects, colCnt) {
+ var rectsByEachCol = [];
+ for (var col = 0; col < colCnt; col += 1) {
+ rectsByEachCol.push([]);
+ }
+ for (var _i = 0, rects_3 = rects; _i < rects_3.length; _i++) {
+ var rect = rects_3[_i];
+ for (var col = rect.span.start; col < rect.span.end; col += 1) {
+ rectsByEachCol[col].push(rect);
+ }
+ }
+ return rectsByEachCol;
+ }
+ function resliceSeg(seg, spanStart, spanEnd, cells) {
+ if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
+ return seg;
+ }
+ var eventRange = seg.eventRange;
+ var origRange = eventRange.range;
+ var slicedRange = intersectRanges(origRange, {
+ start: cells[spanStart].date,
+ end: addDays(cells[spanEnd - 1].date, 1)
+ });
+ return __assign(__assign({}, seg), {
+ firstCol: spanStart,
+ lastCol: spanEnd - 1,
+ eventRange: {
+ def: eventRange.def,
+ ui: __assign(__assign({}, eventRange.ui), { durationEditable: false }),
+ instance: eventRange.instance,
+ range: slicedRange
+ },
+ isStart:
+ seg.isStart &&
+ slicedRange.start.valueOf() === origRange.start.valueOf(),
+ isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf()
+ });
+ }
+ var DayGridSegHierarchy = /** @class */ (function(_super) {
+ __extends(DayGridSegHierarchy, _super);
+ function DayGridSegHierarchy() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ // config
+ _this.hiddenConsumes = false;
+ // allows us to keep hidden entries in the hierarchy so they take up space
+ _this.forceHidden = {};
+ return _this;
+ }
+ DayGridSegHierarchy.prototype.addSegs = function(segInputs) {
+ var _this = this;
+ var hiddenSegs = _super.prototype.addSegs.call(this, segInputs);
+ var entriesByLevel = this.entriesByLevel;
+ var excludeHidden = function(entry) {
+ return !_this.forceHidden[buildEntryKey(entry)];
+ };
+ // remove the forced-hidden segs
+ for (var level = 0; level < entriesByLevel.length; level += 1) {
+ entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
+ }
+ return hiddenSegs;
+ };
+ DayGridSegHierarchy.prototype.handleInvalidInsertion = function(
+ insertion,
+ entry,
+ hiddenEntries
+ ) {
+ var _a = this,
+ entriesByLevel = _a.entriesByLevel,
+ forceHidden = _a.forceHidden;
+ var touchingEntry = insertion.touchingEntry,
+ touchingLevel = insertion.touchingLevel,
+ touchingLateral = insertion.touchingLateral;
+ if (this.hiddenConsumes && touchingEntry) {
+ var touchingEntryId = buildEntryKey(touchingEntry);
+ // if not already hidden
+ if (!forceHidden[touchingEntryId]) {
+ if (this.allowReslicing) {
+ var placeholderEntry = __assign(__assign({}, touchingEntry), {
+ span: intersectSpans(touchingEntry.span, entry.span)
+ });
+ var placeholderEntryId = buildEntryKey(placeholderEntry);
+ forceHidden[placeholderEntryId] = true;
+ entriesByLevel[touchingLevel][touchingLateral] = placeholderEntry; // replace touchingEntry with our placeholder
+ this.splitEntry(touchingEntry, entry, hiddenEntries); // split up the touchingEntry, reinsert it
+ } else {
+ forceHidden[touchingEntryId] = true;
+ hiddenEntries.push(touchingEntry);
+ }
+ }
+ }
+ return _super.prototype.handleInvalidInsertion.call(
+ this,
+ insertion,
+ entry,
+ hiddenEntries
+ );
+ };
+ return DayGridSegHierarchy;
+ })(SegHierarchy);
+
+ var TableRow = /** @class */ (function(_super) {
+ __extends(TableRow, _super);
+ function TableRow() {
+ var _this = (_super !== null && _super.apply(this, arguments)) || this;
+ _this.cellElRefs = new RefMap(); // the
a";
-
- // Support tests won't run in some limited or non-browser environments
- all = div.getElementsByTagName("*");
- a = div.getElementsByTagName("a")[ 0 ];
- if ( !all || !a || !all.length ) {
- return {};
- }
-
- // First batch of tests
- select = document.createElement("select");
- opt = select.appendChild( document.createElement("option") );
- input = div.getElementsByTagName("input")[ 0 ];
-
- a.style.cssText = "top:1px;float:left;opacity:.5";
- support = {
- // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
- getSetAttribute: div.className !== "t",
-
- // IE strips leading whitespace when .innerHTML is used
- leadingWhitespace: div.firstChild.nodeType === 3,
-
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- tbody: !div.getElementsByTagName("tbody").length,
-
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- htmlSerialize: !!div.getElementsByTagName("link").length,
-
- // Get the style information from getAttribute
- // (IE uses .cssText instead)
- style: /top/.test( a.getAttribute("style") ),
-
- // Make sure that URLs aren't manipulated
- // (IE normalizes it by default)
- hrefNormalized: a.getAttribute("href") === "/a",
-
- // Make sure that element opacity exists
- // (IE uses filter instead)
- // Use a regex to work around a WebKit issue. See #5145
- opacity: /^0.5/.test( a.style.opacity ),
-
- // Verify style float existence
- // (IE uses styleFloat instead of cssFloat)
- cssFloat: !!a.style.cssFloat,
-
- // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
- checkOn: !!input.value,
-
- // Make sure that a selected-by-default option has a working selected property.
- // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
- optSelected: opt.selected,
-
- // Tests for enctype support on a form (#6743)
- enctype: !!document.createElement("form").enctype,
-
- // Makes sure cloning an html5 element does not cause problems
- // Where outerHTML is undefined, this still works
- html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>",
-
- // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
- boxModel: document.compatMode === "CSS1Compat",
-
- // Will be defined later
- deleteExpando: true,
- noCloneEvent: true,
- inlineBlockNeedsLayout: false,
- shrinkWrapBlocks: false,
- reliableMarginRight: true,
- boxSizingReliable: true,
- pixelPosition: false
- };
-
- // Make sure checked status is properly cloned
- input.checked = true;
- support.noCloneChecked = input.cloneNode( true ).checked;
-
- // Make sure that the options inside disabled selects aren't marked as disabled
- // (WebKit marks them as disabled)
- select.disabled = true;
- support.optDisabled = !opt.disabled;
-
- // Support: IE<9
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
-
- // Check if we can trust getAttribute("value")
- input = document.createElement("input");
- input.setAttribute( "value", "" );
- support.input = input.getAttribute( "value" ) === "";
-
- // Check if an input maintains its value after becoming a radio
- input.value = "t";
- input.setAttribute( "type", "radio" );
- support.radioValue = input.value === "t";
-
- // #11217 - WebKit loses check when the name is after the checked attribute
- input.setAttribute( "checked", "t" );
- input.setAttribute( "name", "t" );
-
- fragment = document.createDocumentFragment();
- fragment.appendChild( input );
-
- // Check if a disconnected checkbox will retain its checked
- // value of true after appended to the DOM (IE6/7)
- support.appendChecked = input.checked;
-
- // WebKit doesn't clone checked state correctly in fragments
- support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Support: IE<9
- // Opera does not clone events (and typeof div.attachEvent === undefined).
- // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
- if ( div.attachEvent ) {
- div.attachEvent( "onclick", function() {
- support.noCloneEvent = false;
- });
-
- div.cloneNode( true ).click();
- }
-
- // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
- // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
- for ( i in { submit: true, change: true, focusin: true }) {
- div.setAttribute( eventName = "on" + i, "t" );
-
- support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
- }
-
- div.style.backgroundClip = "content-box";
- div.cloneNode( true ).style.backgroundClip = "";
- support.clearCloneStyle = div.style.backgroundClip === "content-box";
-
- // Run tests that need a body at doc ready
- jQuery(function() {
- var container, marginDiv, tds,
- divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
- body = document.getElementsByTagName("body")[0];
-
- if ( !body ) {
- // Return for frameset docs that don't have a body
- return;
- }
-
- container = document.createElement("div");
- container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
-
- body.appendChild( container ).appendChild( div );
-
- // Support: IE8
- // Check if table cells still have offsetWidth/Height when they are set
- // to display:none and there are still other visible table cells in a
- // table row; if so, offsetWidth/Height are not reliable for use when
- // determining if an element has been hidden directly using
- // display:none (it is still safe to use offsets if a parent element is
- // hidden; don safety goggles and see bug #4512 for more information).
- div.innerHTML = "
t
";
- tds = div.getElementsByTagName("td");
- tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
- isSupported = ( tds[ 0 ].offsetHeight === 0 );
-
- tds[ 0 ].style.display = "";
- tds[ 1 ].style.display = "none";
-
- // Support: IE8
- // Check if empty table cells still have offsetWidth/Height
- support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
-
- // Check box-sizing and margin behavior
- div.innerHTML = "";
- div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
- support.boxSizing = ( div.offsetWidth === 4 );
- support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
-
- // Use window.getComputedStyle because jsdom on node.js will break without it.
- if ( window.getComputedStyle ) {
- support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
- support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
-
- // Check if div with explicit width and no margin-right incorrectly
- // gets computed margin-right based on width of container. (#3333)
- // Fails in WebKit before Feb 2011 nightlies
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- marginDiv = div.appendChild( document.createElement("div") );
- marginDiv.style.cssText = div.style.cssText = divReset;
- marginDiv.style.marginRight = marginDiv.style.width = "0";
- div.style.width = "1px";
-
- support.reliableMarginRight =
- !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
- }
-
- if ( typeof div.style.zoom !== core_strundefined ) {
- // Support: IE<8
- // Check if natively block-level elements act like inline-block
- // elements when setting their display to 'inline' and giving
- // them layout
- div.innerHTML = "";
- div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
- support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
-
- // Support: IE6
- // Check if elements with layout shrink-wrap their children
- div.style.display = "block";
- div.innerHTML = "";
- div.firstChild.style.width = "5px";
- support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
-
- if ( support.inlineBlockNeedsLayout ) {
- // Prevent IE 6 from affecting layout for positioned elements #11048
- // Prevent IE from shrinking the body in IE 7 mode #12869
- // Support: IE<8
- body.style.zoom = 1;
- }
- }
-
- body.removeChild( container );
-
- // Null elements to avoid leaks in IE
- container = div = tds = marginDiv = null;
- });
-
- // Null elements to avoid leaks in IE
- all = select = fragment = opt = a = input = null;
-
- return support;
-})();
-
-var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
- rmultiDash = /([A-Z])/g;
-
-function internalData( elem, name, data, pvt /* Internal Use Only */ ){
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var thisCache, ret,
- internalKey = jQuery.expando,
- getByName = typeof name === "string",
-
- // We have to handle DOM nodes and JS objects differently because IE6-7
- // can't GC object references properly across the DOM-JS boundary
- isNode = elem.nodeType,
-
- // Only DOM nodes need the global jQuery cache; JS object data is
- // attached directly to the object so GC can occur automatically
- cache = isNode ? jQuery.cache : elem,
-
- // Only defining an ID for JS objects if its cache already exists allows
- // the code to shortcut on the same path as a DOM node with no cache
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
-
- // Avoid doing any more work than we need to when trying to get data on an
- // object that has no data at all
- if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
- return;
- }
-
- if ( !id ) {
- // Only DOM nodes need a new unique ID for each element since their data
- // ends up in the global cache
- if ( isNode ) {
- elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
- } else {
- id = internalKey;
- }
- }
-
- if ( !cache[ id ] ) {
- cache[ id ] = {};
-
- // Avoids exposing jQuery metadata on plain JS objects when the object
- // is serialized using JSON.stringify
- if ( !isNode ) {
- cache[ id ].toJSON = jQuery.noop;
- }
- }
-
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
- // shallow copied over onto the existing cache
- if ( typeof name === "object" || typeof name === "function" ) {
- if ( pvt ) {
- cache[ id ] = jQuery.extend( cache[ id ], name );
- } else {
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
- }
- }
-
- thisCache = cache[ id ];
-
- // jQuery data() is stored in a separate object inside the object's internal data
- // cache in order to avoid key collisions between internal data and user-defined
- // data.
- if ( !pvt ) {
- if ( !thisCache.data ) {
- thisCache.data = {};
- }
-
- thisCache = thisCache.data;
- }
-
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
-
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( getByName ) {
-
- // First Try to find as-is property data
- ret = thisCache[ name ];
-
- // Test for null|undefined property data
- if ( ret == null ) {
-
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
- }
- } else {
- ret = thisCache;
- }
-
- return ret;
-}
-
-function internalRemoveData( elem, name, pvt ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var i, l, thisCache,
- isNode = elem.nodeType,
-
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
- id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
-
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
- }
-
- if ( name ) {
-
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
- if ( thisCache ) {
-
- // Support array or space separated string names for data keys
- if ( !jQuery.isArray( name ) ) {
-
- // try the string as a key before any manipulation
- if ( name in thisCache ) {
- name = [ name ];
- } else {
-
- // split the camel cased version by spaces unless a key with the spaces exists
- name = jQuery.camelCase( name );
- if ( name in thisCache ) {
- name = [ name ];
- } else {
- name = name.split(" ");
- }
- }
- } else {
- // If "name" is an array of keys...
- // When data is initially created, via ("key", "val") signature,
- // keys will be converted to camelCase.
- // Since there is no way to tell _how_ a key was added, remove
- // both plain key and camelCase key. #12786
- // This will only penalize the array argument path.
- name = name.concat( jQuery.map( name, jQuery.camelCase ) );
- }
-
- for ( i = 0, l = name.length; i < l; i++ ) {
- delete thisCache[ name[i] ];
- }
-
- // If there is no data left in the cache, we want to continue
- // and let the cache object itself get destroyed
- if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
- return;
- }
- }
- }
-
- // See jQuery.data for more information
- if ( !pvt ) {
- delete cache[ id ].data;
-
- // Don't destroy the parent cache unless the internal data object
- // had been the only thing left in it
- if ( !isEmptyDataObject( cache[ id ] ) ) {
- return;
- }
- }
-
- // Destroy the cache
- if ( isNode ) {
- jQuery.cleanData( [ elem ], true );
-
- // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
- } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
- delete cache[ id ];
-
- // When all else fails, null
- } else {
- cache[ id ] = null;
- }
-}
-
-jQuery.extend({
- cache: {},
-
- // Unique for each copy of jQuery on the page
- // Non-digits removed to match rinlinejQuery
- expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
-
- // The following elements throw uncatchable exceptions if you
- // attempt to add expando properties to them.
- noData: {
- "embed": true,
- // Ban all objects except for Flash (which handle expandos)
- "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
- "applet": true
- },
-
- hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
- },
-
- data: function( elem, name, data ) {
- return internalData( elem, name, data );
- },
-
- removeData: function( elem, name ) {
- return internalRemoveData( elem, name );
- },
-
- // For internal use only.
- _data: function( elem, name, data ) {
- return internalData( elem, name, data, true );
- },
-
- _removeData: function( elem, name ) {
- return internalRemoveData( elem, name, true );
- },
-
- // A method for determining if a DOM node can handle the data expando
- acceptData: function( elem ) {
- // Do not set data on non-element because it will not be cleared (#8335).
- if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
- return false;
- }
-
- var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
-
- // nodes accept data unless otherwise specified; rejection can be conditional
- return !noData || noData !== true && elem.getAttribute("classid") === noData;
- }
-});
-
-jQuery.fn.extend({
- data: function( key, value ) {
- var attrs, name,
- elem = this[0],
- i = 0,
- data = null;
-
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = jQuery.data( elem );
-
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
- attrs = elem.attributes;
- for ( ; i < attrs.length; i++ ) {
- name = attrs[i].name;
-
- if ( !name.indexOf( "data-" ) ) {
- name = jQuery.camelCase( name.slice(5) );
-
- dataAttr( elem, name, data[ name ] );
- }
- }
- jQuery._data( elem, "parsedAttrs", true );
- }
- }
-
- return data;
- }
-
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
- }
-
- return jQuery.access( this, function( value ) {
-
- if ( value === undefined ) {
- // Try to fetch any internally stored data first
- return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
- }
-
- this.each(function() {
- jQuery.data( this, key, value );
- });
- }, null, value, arguments.length > 1, null, true );
- },
-
- removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
- }
-});
-
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
-
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
-
- } else {
- data = undefined;
- }
- }
-
- return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- var name;
- for ( name in obj ) {
-
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
- }
- }
-
- return true;
-}
-jQuery.extend({
- queue: function( elem, type, data ) {
- var queue;
-
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = jQuery._data( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || jQuery.isArray(data) ) {
- queue = jQuery._data( elem, type, jQuery.makeArray(data) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- startLength = queue.length,
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- startLength--;
- }
-
- hooks.cur = fn;
- if ( fn ) {
-
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- // clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
-
- if ( !startLength && hooks ) {
- hooks.empty.fire();
- }
- },
-
- // not intended for public consumption - generates a queueHooks object, or returns the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return jQuery._data( elem, key ) || jQuery._data( elem, key, {
- empty: jQuery.Callbacks("once memory").add(function() {
- jQuery._removeData( elem, type + "queue" );
- jQuery._removeData( elem, key );
- })
- });
- }
-});
-
-jQuery.fn.extend({
- queue: function( type, data ) {
- var setter = 2;
-
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
-
- if ( arguments.length < setter ) {
- return jQuery.queue( this[0], type );
- }
-
- return data === undefined ?
- this :
- this.each(function() {
- var queue = jQuery.queue( this, type, data );
-
- // ensure a hooks for this queue
- jQuery._queueHooks( this, type );
-
- if ( type === "fx" && queue[0] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- });
- },
- dequeue: function( type ) {
- return this.each(function() {
- jQuery.dequeue( this, type );
- });
- },
- // Based off of the plugin by Clint Helfers, with permission.
- // http://blindsignals.com/index.php/2009/07/jquery-delay/
- delay: function( time, type ) {
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
- type = type || "fx";
-
- return this.queue( type, function( next, hooks ) {
- var timeout = setTimeout( next, time );
- hooks.stop = function() {
- clearTimeout( timeout );
- };
- });
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- };
-
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
-
- while( i-- ) {
- tmp = jQuery._data( elements[ i ], type + "queueHooks" );
- if ( tmp && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
- }
- resolve();
- return defer.promise( obj );
- }
-});
-var nodeHook, boolHook,
- rclass = /[\t\r\n]/g,
- rreturn = /\r/g,
- rfocusable = /^(?:input|select|textarea|button|object)$/i,
- rclickable = /^(?:a|area)$/i,
- rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
- ruseDefault = /^(?:checked|selected)$/i,
- getSetAttribute = jQuery.support.getSetAttribute,
- getSetInput = jQuery.support.input;
-
-jQuery.fn.extend({
- attr: function( name, value ) {
- return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
- },
-
- removeAttr: function( name ) {
- return this.each(function() {
- jQuery.removeAttr( this, name );
- });
- },
-
- prop: function( name, value ) {
- return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
- },
-
- removeProp: function( name ) {
- name = jQuery.propFix[ name ] || name;
- return this.each(function() {
- // try/catch handles cases where IE balks (such as removing a property on window)
- try {
- this[ name ] = undefined;
- delete this[ name ];
- } catch( e ) {}
- });
- },
-
- addClass: function( value ) {
- var classes, elem, cur, clazz, j,
- i = 0,
- len = this.length,
- proceed = typeof value === "string" && value;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).addClass( value.call( this, j, this.className ) );
- });
- }
-
- if ( proceed ) {
- // The disjunction here is for better compressibility (see removeClass)
- classes = ( value || "" ).match( core_rnotwhite ) || [];
-
- for ( ; i < len; i++ ) {
- elem = this[ i ];
- cur = elem.nodeType === 1 && ( elem.className ?
- ( " " + elem.className + " " ).replace( rclass, " " ) :
- " "
- );
-
- if ( cur ) {
- j = 0;
- while ( (clazz = classes[j++]) ) {
- if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
- cur += clazz + " ";
- }
- }
- elem.className = jQuery.trim( cur );
-
- }
- }
- }
-
- return this;
- },
-
- removeClass: function( value ) {
- var classes, elem, cur, clazz, j,
- i = 0,
- len = this.length,
- proceed = arguments.length === 0 || typeof value === "string" && value;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).removeClass( value.call( this, j, this.className ) );
- });
- }
- if ( proceed ) {
- classes = ( value || "" ).match( core_rnotwhite ) || [];
-
- for ( ; i < len; i++ ) {
- elem = this[ i ];
- // This expression is here for better compressibility (see addClass)
- cur = elem.nodeType === 1 && ( elem.className ?
- ( " " + elem.className + " " ).replace( rclass, " " ) :
- ""
- );
-
- if ( cur ) {
- j = 0;
- while ( (clazz = classes[j++]) ) {
- // Remove *all* instances
- while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
- cur = cur.replace( " " + clazz + " ", " " );
- }
- }
- elem.className = value ? jQuery.trim( cur ) : "";
- }
- }
- }
-
- return this;
- },
-
- toggleClass: function( value, stateVal ) {
- var type = typeof value,
- isBool = typeof stateVal === "boolean";
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( i ) {
- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
- });
- }
-
- return this.each(function() {
- if ( type === "string" ) {
- // toggle individual class names
- var className,
- i = 0,
- self = jQuery( this ),
- state = stateVal,
- classNames = value.match( core_rnotwhite ) || [];
-
- while ( (className = classNames[ i++ ]) ) {
- // check each className given, space separated list
- state = isBool ? state : !self.hasClass( className );
- self[ state ? "addClass" : "removeClass" ]( className );
- }
-
- // Toggle whole class name
- } else if ( type === core_strundefined || type === "boolean" ) {
- if ( this.className ) {
- // store className if set
- jQuery._data( this, "__className__", this.className );
- }
-
- // If the element has a class name or if we're passed "false",
- // then remove the whole classname (if there was one, the above saved it).
- // Otherwise bring back whatever was previously saved (if anything),
- // falling back to the empty string if nothing was stored.
- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
- }
- });
- },
-
- hasClass: function( selector ) {
- var className = " " + selector + " ",
- i = 0,
- l = this.length;
- for ( ; i < l; i++ ) {
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
- return true;
- }
- }
-
- return false;
- },
-
- val: function( value ) {
- var ret, hooks, isFunction,
- elem = this[0];
-
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
-
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
- return ret;
- }
-
- ret = elem.value;
-
- return typeof ret === "string" ?
- // handle most common string cases
- ret.replace(rreturn, "") :
- // handle cases where value is null/undef or number
- ret == null ? "" : ret;
- }
-
- return;
- }
-
- isFunction = jQuery.isFunction( value );
-
- return this.each(function( i ) {
- var val,
- self = jQuery(this);
-
- if ( this.nodeType !== 1 ) {
- return;
- }
-
- if ( isFunction ) {
- val = value.call( this, i, self.val() );
- } else {
- val = value;
- }
-
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
- } else if ( typeof val === "number" ) {
- val += "";
- } else if ( jQuery.isArray( val ) ) {
- val = jQuery.map(val, function ( value ) {
- return value == null ? "" : value + "";
- });
- }
-
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
-
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
- }
- });
- }
-});
-
-jQuery.extend({
- valHooks: {
- option: {
- get: function( elem ) {
- // attributes.value is undefined in Blackberry 4.7 but
- // uses .value. See #6932
- var val = elem.attributes.value;
- return !val || val.specified ? elem.value : elem.text;
- }
- },
- select: {
- get: function( elem ) {
- var value, option,
- options = elem.options,
- index = elem.selectedIndex,
- one = elem.type === "select-one" || index < 0,
- values = one ? null : [],
- max = one ? index + 1 : options.length,
- i = index < 0 ?
- max :
- one ? index : 0;
-
- // Loop through all the selected options
- for ( ; i < max; i++ ) {
- option = options[ i ];
-
- // oldIE doesn't update selected after form reset (#2551)
- if ( ( option.selected || i === index ) &&
- // Don't return options that are disabled or in a disabled optgroup
- ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
- ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
-
- // Get the specific value for the option
- value = jQuery( option ).val();
-
- // We don't need an array for one selects
- if ( one ) {
- return value;
- }
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- return values;
- },
-
- set: function( elem, value ) {
- var values = jQuery.makeArray( value );
-
- jQuery(elem).find("option").each(function() {
- this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
- });
-
- if ( !values.length ) {
- elem.selectedIndex = -1;
- }
- return values;
- }
- }
- },
-
- attr: function( elem, name, value ) {
- var hooks, notxml, ret,
- nType = elem.nodeType;
-
- // don't get/set attributes on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- // Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === core_strundefined ) {
- return jQuery.prop( elem, name, value );
- }
-
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
- // All attributes are lowercase
- // Grab necessary hook if one is defined
- if ( notxml ) {
- name = name.toLowerCase();
- hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
- }
-
- if ( value !== undefined ) {
-
- if ( value === null ) {
- jQuery.removeAttr( elem, name );
-
- } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
-
- } else {
- elem.setAttribute( name, value + "" );
- return value;
- }
-
- } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
-
- // In IE9+, Flash objects don't have .getAttribute (#12945)
- // Support: IE9+
- if ( typeof elem.getAttribute !== core_strundefined ) {
- ret = elem.getAttribute( name );
- }
-
- // Non-existent attributes return null, we normalize to undefined
- return ret == null ?
- undefined :
- ret;
- }
- },
-
- removeAttr: function( elem, value ) {
- var name, propName,
- i = 0,
- attrNames = value && value.match( core_rnotwhite );
-
- if ( attrNames && elem.nodeType === 1 ) {
- while ( (name = attrNames[i++]) ) {
- propName = jQuery.propFix[ name ] || name;
-
- // Boolean attributes get special treatment (#10870)
- if ( rboolean.test( name ) ) {
- // Set corresponding property to false for boolean attributes
- // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
- if ( !getSetAttribute && ruseDefault.test( name ) ) {
- elem[ jQuery.camelCase( "default-" + name ) ] =
- elem[ propName ] = false;
- } else {
- elem[ propName ] = false;
- }
-
- // See #9699 for explanation of this approach (setting first, then removal)
- } else {
- jQuery.attr( elem, name, "" );
- }
-
- elem.removeAttribute( getSetAttribute ? name : propName );
- }
- }
- },
-
- attrHooks: {
- type: {
- set: function( elem, value ) {
- if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
- // Setting the type on a radio button after the value resets the value in IE6-9
- // Reset value to default in case type is set after value during creation
- var val = elem.value;
- elem.setAttribute( "type", value );
- if ( val ) {
- elem.value = val;
- }
- return value;
- }
- }
- }
- },
-
- propFix: {
- tabindex: "tabIndex",
- readonly: "readOnly",
- "for": "htmlFor",
- "class": "className",
- maxlength: "maxLength",
- cellspacing: "cellSpacing",
- cellpadding: "cellPadding",
- rowspan: "rowSpan",
- colspan: "colSpan",
- usemap: "useMap",
- frameborder: "frameBorder",
- contenteditable: "contentEditable"
- },
-
- prop: function( elem, name, value ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
-
- // don't get/set properties on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
- if ( notxml ) {
- // Fix name and attach hooks
- name = jQuery.propFix[ name ] || name;
- hooks = jQuery.propHooks[ name ];
- }
-
- if ( value !== undefined ) {
- if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
-
- } else {
- return ( elem[ name ] = value );
- }
-
- } else {
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
- return elem[ name ];
- }
- }
- },
-
- propHooks: {
- tabIndex: {
- get: function( elem ) {
- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- var attributeNode = elem.getAttributeNode("tabindex");
-
- return attributeNode && attributeNode.specified ?
- parseInt( attributeNode.value, 10 ) :
- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
- 0 :
- undefined;
- }
- }
- }
-});
-
-// Hook for boolean attributes
-boolHook = {
- get: function( elem, name ) {
- var
- // Use .prop to determine if this attribute is understood as boolean
- prop = jQuery.prop( elem, name ),
-
- // Fetch it accordingly
- attr = typeof prop === "boolean" && elem.getAttribute( name ),
- detail = typeof prop === "boolean" ?
-
- getSetInput && getSetAttribute ?
- attr != null :
- // oldIE fabricates an empty string for missing boolean attributes
- // and conflates checked/selected into attroperties
- ruseDefault.test( name ) ?
- elem[ jQuery.camelCase( "default-" + name ) ] :
- !!attr :
-
- // fetch an attribute node for properties not recognized as boolean
- elem.getAttributeNode( name );
-
- return detail && detail.value !== false ?
- name.toLowerCase() :
- undefined;
- },
- set: function( elem, value, name ) {
- if ( value === false ) {
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
- // IE<8 needs the *property* name
- elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
-
- // Use defaultChecked and defaultSelected for oldIE
- } else {
- elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
- }
-
- return name;
- }
-};
-
-// fix oldIE value attroperty
-if ( !getSetInput || !getSetAttribute ) {
- jQuery.attrHooks.value = {
- get: function( elem, name ) {
- var ret = elem.getAttributeNode( name );
- return jQuery.nodeName( elem, "input" ) ?
-
- // Ignore the value *property* by using defaultValue
- elem.defaultValue :
-
- ret && ret.specified ? ret.value : undefined;
- },
- set: function( elem, value, name ) {
- if ( jQuery.nodeName( elem, "input" ) ) {
- // Does not return so that setAttribute is also used
- elem.defaultValue = value;
- } else {
- // Use nodeHook if defined (#1954); otherwise setAttribute is fine
- return nodeHook && nodeHook.set( elem, value, name );
- }
- }
- };
-}
-
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
-
- // Use this for any attribute in IE6/7
- // This fixes almost every IE6/7 issue
- nodeHook = jQuery.valHooks.button = {
- get: function( elem, name ) {
- var ret = elem.getAttributeNode( name );
- return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
- ret.value :
- undefined;
- },
- set: function( elem, value, name ) {
- // Set the existing or create a new attribute node
- var ret = elem.getAttributeNode( name );
- if ( !ret ) {
- elem.setAttributeNode(
- (ret = elem.ownerDocument.createAttribute( name ))
- );
- }
-
- ret.value = value += "";
-
- // Break association with cloned elements by also using setAttribute (#9646)
- return name === "value" || value === elem.getAttribute( name ) ?
- value :
- undefined;
- }
- };
-
- // Set contenteditable to false on removals(#10429)
- // Setting to empty string throws an error as an invalid value
- jQuery.attrHooks.contenteditable = {
- get: nodeHook.get,
- set: function( elem, value, name ) {
- nodeHook.set( elem, value === "" ? false : value, name );
- }
- };
-
- // Set width and height to auto instead of 0 on empty string( Bug #8150 )
- // This is for removals
- jQuery.each([ "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- set: function( elem, value ) {
- if ( value === "" ) {
- elem.setAttribute( name, "auto" );
- return value;
- }
- }
- });
- });
-}
-
-
-// Some attributes require a special call on IE
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !jQuery.support.hrefNormalized ) {
- jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- get: function( elem ) {
- var ret = elem.getAttribute( name, 2 );
- return ret == null ? undefined : ret;
- }
- });
- });
-
- // href/src property should get the full normalized URL (#10299/#12915)
- jQuery.each([ "href", "src" ], function( i, name ) {
- jQuery.propHooks[ name ] = {
- get: function( elem ) {
- return elem.getAttribute( name, 4 );
- }
- };
- });
-}
-
-if ( !jQuery.support.style ) {
- jQuery.attrHooks.style = {
- get: function( elem ) {
- // Return undefined in the case of empty string
- // Note: IE uppercases css property names, but if we were to .toLowerCase()
- // .cssText, that would destroy case senstitivity in URL's, like in "background"
- return elem.style.cssText || undefined;
- },
- set: function( elem, value ) {
- return ( elem.style.cssText = value + "" );
- }
- };
-}
-
-// Safari mis-reports the default selected property of an option
-// Accessing the parent's selectedIndex property fixes it
-if ( !jQuery.support.optSelected ) {
- jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
- get: function( elem ) {
- var parent = elem.parentNode;
-
- if ( parent ) {
- parent.selectedIndex;
-
- // Make sure that it also works with optgroups, see #5701
- if ( parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- }
- return null;
- }
- });
-}
-
-// IE6/7 call enctype encoding
-if ( !jQuery.support.enctype ) {
- jQuery.propFix.enctype = "encoding";
-}
-
-// Radios and checkboxes getter/setter
-if ( !jQuery.support.checkOn ) {
- jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = {
- get: function( elem ) {
- // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
- return elem.getAttribute("value") === null ? "on" : elem.value;
- }
- };
- });
-}
-jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
- set: function( elem, value ) {
- if ( jQuery.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
- }
- }
- });
-});
-var rformElems = /^(?:input|select|textarea)$/i,
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
-
-function returnTrue() {
- return true;
-}
-
-function returnFalse() {
- return false;
-}
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- global: {},
-
- add: function( elem, types, handler, data, selector ) {
- var tmp, events, t, handleObjIn,
- special, eventHandle, handleObj,
- handlers, type, namespaces, origType,
- elemData = jQuery._data( elem );
-
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
- if ( !elemData ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- if ( !(events = elemData.events) ) {
- events = elemData.events = {};
- }
- if ( !(eventHandle = elemData.handle) ) {
- eventHandle = elemData.handle = function( e ) {
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
- };
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
- }
-
- // Handle multiple events separated by a space
- // jQuery(...).bind("mouseover mouseout", fn);
- types = ( types || "" ).match( core_rnotwhite ) || [""];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend({
- type: type,
- origType: origType,
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join(".")
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- if ( !(handlers = events[ type ]) ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
-
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
- var j, handleObj, tmp,
- origCount, t, events,
- special, handlers, type,
- namespaces, origType,
- elemData = jQuery.hasData( elem ) && jQuery._data( elem );
-
- if ( !elemData || !(events = elemData.events) ) {
- return;
- }
-
- // Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( core_rnotwhite ) || [""];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- special = jQuery.event.special[ type ] || {};
- type = ( selector ? special.delegateType : special.bindType ) || type;
- handlers = events[ type ] || [];
- tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
-
- // Remove matching events
- origCount = j = handlers.length;
- while ( j-- ) {
- handleObj = handlers[ j ];
-
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
- handlers.splice( j, 1 );
-
- if ( handleObj.selector ) {
- handlers.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( origCount && !handlers.length ) {
- if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- delete elemData.handle;
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery._removeData( elem, "events" );
- }
- },
-
- trigger: function( event, data, elem, onlyHandlers ) {
- var handle, ontype, cur,
- bubbleType, special, tmp, i,
- eventPath = [ elem || document ],
- type = core_hasOwn.call( event, "type" ) ? event.type : event,
- namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
-
- cur = tmp = elem = elem || document;
-
- // Don't do events on text and comment nodes
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
- return;
- }
-
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf(".") >= 0 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
- ontype = type.indexOf(":") < 0 && "on" + type;
-
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
- event = event[ jQuery.expando ] ?
- event :
- new jQuery.Event( type, typeof event === "object" && event );
-
- event.isTrigger = true;
- event.namespace = namespaces.join(".");
- event.namespace_re = event.namespace ?
- new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
- null;
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data == null ?
- [ event ] :
- jQuery.makeArray( data, [ event ] );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
-
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- if ( !rfocusMorph.test( bubbleType + type ) ) {
- cur = cur.parentNode;
- }
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push( cur );
- tmp = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( tmp === (elem.ownerDocument || document) ) {
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
- }
- }
-
- // Fire handlers on the event path
- i = 0;
- while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
-
- event.type = i > 1 ?
- bubbleType :
- special.bindType || type;
-
- // jQuery handler
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
-
- // Native handler
- handle = ontype && cur[ ontype ];
- if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
- event.preventDefault();
- }
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
- if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
- !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name name as the event.
- // Can't use an .isFunction() check here because IE6/7 fails that test.
- // Don't do default actions on window, that's where global variables be (#6170)
- if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- tmp = elem[ ontype ];
-
- if ( tmp ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- try {
- elem[ type ]();
- } catch ( e ) {
- // IE<9 dies on focus/blur to hidden element (#1486,#12518)
- // only reproducible on winXP IE8 native, not IE9 in IE8 mode
- }
- jQuery.event.triggered = undefined;
-
- if ( tmp ) {
- elem[ ontype ] = tmp;
- }
- }
- }
- }
-
- return event.result;
- },
-
- dispatch: function( event ) {
-
- // Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event );
-
- var i, ret, handleObj, matched, j,
- handlerQueue = [],
- args = core_slice.call( arguments ),
- handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
- event.delegateTarget = this;
-
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
-
- // Determine handlers
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
-
- // Run delegates first; they may want to stop propagation beneath us
- i = 0;
- while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
- event.currentTarget = matched.elem;
-
- j = 0;
- while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
-
- // Triggered event must either 1) have no namespace, or
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
-
- event.handleObj = handleObj;
- event.data = handleObj.data;
-
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- if ( (event.result = ret) === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
-
- handlers: function( event, handlers ) {
- var sel, handleObj, matches, i,
- handlerQueue = [],
- delegateCount = handlers.delegateCount,
- cur = event.target;
-
- // Find delegate handlers
- // Black-hole SVG