From 4f734e0f374428be6424faee0a56458d4fa80396 Mon Sep 17 00:00:00 2001 From: polo Date: Tue, 23 Dec 2025 21:34:47 +0100 Subject: installation de fullcalendar avec composer et CDN au lieu de GIT --- .../packages/interaction/index.global.js | 2141 -------------------- .../packages/interaction/index.global.min.js | 6 - 2 files changed, 2147 deletions(-) delete mode 100644 public/js/fullcalendar/packages/interaction/index.global.js delete mode 100644 public/js/fullcalendar/packages/interaction/index.global.min.js (limited to 'public/js/fullcalendar/packages/interaction') diff --git a/public/js/fullcalendar/packages/interaction/index.global.js b/public/js/fullcalendar/packages/interaction/index.global.js deleted file mode 100644 index d05a22e..0000000 --- a/public/js/fullcalendar/packages/interaction/index.global.js +++ /dev/null @@ -1,2141 +0,0 @@ -/*! -FullCalendar Interaction Plugin v6.1.17 -Docs & License: https://fullcalendar.io/docs/editable -(c) 2024 Adam Shaw -*/ -FullCalendar.Interaction = (function (exports, core, internal) { - 'use strict'; - - internal.config.touchMouseIgnoreWait = 500; - let ignoreMouseDepth = 0; - let listenerCnt = 0; - let 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 - */ - class PointerDragging { - constructor(containerEl) { - 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 = (ev) => { - if (!this.shouldIgnoreMouse() && - isPrimaryMouseButton(ev) && - this.tryStart(ev)) { - let 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 = (ev) => { - let pev = this.createEventFromMouse(ev); - this.recordCoords(pev); - this.emitter.trigger('pointermove', pev); - }; - this.handleMouseUp = (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 = (ev) => { - if (this.tryStart(ev)) { - this.isTouchDragging = true; - let 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 - let 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 = (ev) => { - let pev = this.createEventFromTouch(ev); - this.recordCoords(pev); - this.emitter.trigger('pointermove', pev); - }; - this.handleTouchEnd = (ev) => { - if (this.isDragging) { // done to guard against touchend followed by touchcancel - let 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 = () => { - this.wasTouchScroll = true; - }; - this.handleScroll = (ev) => { - if (!this.shouldIgnoreMove) { - let pageX = (window.scrollX - this.prevScrollX) + this.prevPageX; - let pageY = (window.scrollY - this.prevScrollY) + this.prevPageY; - this.emitter.trigger('pointermove', { - origEvent: ev, - isTouch: this.isTouchDragging, - subjectEl: this.subjectEl, - pageX, - pageY, - deltaX: pageX - this.origPageX, - deltaY: pageY - this.origPageY, - }); - } - }; - this.containerEl = containerEl; - this.emitter = new internal.Emitter(); - containerEl.addEventListener('mousedown', this.handleMouseDown); - containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true }); - listenerCreated(); - } - destroy() { - this.containerEl.removeEventListener('mousedown', this.handleMouseDown); - this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); - listenerDestroyed(); - } - tryStart(ev) { - let subjectEl = this.querySubjectEl(ev); - let downEl = ev.target; - if (subjectEl && - (!this.handleSelector || internal.elementClosest(downEl, this.handleSelector))) { - this.subjectEl = subjectEl; - this.isDragging = true; // do this first so cancelTouchScroll will work - this.wasTouchScroll = false; - return true; - } - return false; - } - cleanup() { - isWindowTouchMoveCancelled = false; - this.isDragging = false; - this.subjectEl = null; - // keep wasTouchScroll around for later access - this.destroyScrollWatch(); - } - querySubjectEl(ev) { - if (this.selector) { - return internal.elementClosest(ev.target, this.selector); - } - return this.containerEl; - } - shouldIgnoreMouse() { - return ignoreMouseDepth || this.isTouchDragging; - } - // can be called by user of this class, to cancel touch-based scrolling for the current drag - cancelTouchScroll() { - if (this.isDragging) { - isWindowTouchMoveCancelled = true; - } - } - // Scrolling that simulates pointermoves - // ---------------------------------------------------------------------------------------------------- - initScrollWatch(ev) { - if (this.shouldWatchScroll) { - this.recordCoords(ev); - window.addEventListener('scroll', this.handleScroll, true); // useCapture=true - } - } - recordCoords(ev) { - if (this.shouldWatchScroll) { - this.prevPageX = ev.pageX; - this.prevPageY = ev.pageY; - this.prevScrollX = window.scrollX; - this.prevScrollY = window.scrollY; - } - } - destroyScrollWatch() { - if (this.shouldWatchScroll) { - window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true - } - } - // Event Normalization - // ---------------------------------------------------------------------------------------------------- - createEventFromMouse(ev, isFirst) { - let deltaX = 0; - let 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, - deltaY, - }; - } - createEventFromTouch(ev, isFirst) { - let touches = ev.touches; - let pageX; - let pageY; - let deltaX = 0; - let 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, - pageY, - deltaX, - deltaY, - }; - } - } - // 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(() => { - ignoreMouseDepth -= 1; - }, internal.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. - */ - class ElementMirror { - constructor() { - 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; - } - start(sourceEl, pageX, pageY) { - this.sourceEl = sourceEl; - this.sourceElRect = this.sourceEl.getBoundingClientRect(); - this.origScreenX = pageX - window.scrollX; - this.origScreenY = pageY - window.scrollY; - this.deltaX = 0; - this.deltaY = 0; - this.updateElPosition(); - } - handleMove(pageX, pageY) { - this.deltaX = (pageX - window.scrollX) - this.origScreenX; - this.deltaY = (pageY - window.scrollY) - this.origScreenY; - this.updateElPosition(); - } - // can be called before start - setIsVisible(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 - stop(needsRevertAnimation, callback) { - let done = () => { - 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); - } - } - doRevertAnimation(callback, revertDuration) { - let mirrorEl = this.mirrorEl; - let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened - mirrorEl.style.transition = - 'top ' + revertDuration + 'ms,' + - 'left ' + revertDuration + 'ms'; - internal.applyStyle(mirrorEl, { - left: finalSourceElRect.left, - top: finalSourceElRect.top, - }); - internal.whenTransitionDone(mirrorEl, () => { - mirrorEl.style.transition = ''; - callback(); - }); - } - cleanup() { - if (this.mirrorEl) { - internal.removeElement(this.mirrorEl); - this.mirrorEl = null; - } - this.sourceEl = null; - } - updateElPosition() { - if (this.sourceEl && this.isVisible) { - internal.applyStyle(this.getMirrorEl(), { - left: this.sourceElRect.left + this.deltaX, - top: this.sourceElRect.top + this.deltaY, - }); - } - } - getMirrorEl() { - let sourceElRect = this.sourceElRect; - let 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.style.userSelect = 'none'; - mirrorEl.style.webkitUserSelect = 'none'; - mirrorEl.style.pointerEvents = 'none'; - mirrorEl.classList.add('fc-event-dragging'); - internal.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; - } - } - - /* - 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 - */ - class ScrollGeomCache extends internal.ScrollController { - constructor(scrollController, doesListening) { - super(); - this.handleScroll = () => { - 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); - } - } - destroy() { - if (this.doesListening) { - this.getEventTarget().removeEventListener('scroll', this.handleScroll); - } - } - getScrollTop() { - return this.scrollTop; - } - getScrollLeft() { - return this.scrollLeft; - } - setScrollTop(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(); - } - } - setScrollLeft(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(); - } - } - getClientWidth() { - return this.clientWidth; - } - getClientHeight() { - return this.clientHeight; - } - getScrollWidth() { - return this.scrollWidth; - } - getScrollHeight() { - return this.scrollHeight; - } - handleScrollChange() { - } - } - - class ElementScrollGeomCache extends ScrollGeomCache { - constructor(el, doesListening) { - super(new internal.ElementScrollController(el), doesListening); - } - getEventTarget() { - return this.scrollController.el; - } - computeClientRect() { - return internal.computeInnerRect(this.scrollController.el); - } - } - - class WindowScrollGeomCache extends ScrollGeomCache { - constructor(doesListening) { - super(new internal.WindowScrollController(), doesListening); - } - getEventTarget() { - return window; - } - computeClientRect() { - 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 - handleScrollChange() { - this.clientRect = this.computeClientRect(); - } - } - - // 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 - const 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. - */ - class AutoScroller { - constructor() { - // 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 = () => { - if (this.isAnimating) { // wasn't cancelled between animation calls - let edge = this.computeBestEdge(this.pointerScreenX + window.scrollX, this.pointerScreenY + window.scrollY); - if (edge) { - let now = getTime(); - this.handleSide(edge, (now - this.msSinceRequest) / 1000); - this.requestAnimation(now); - } - else { - this.isAnimating = false; // will stop animation - } - } - }; - } - start(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); - } - } - handleMove(pageX, pageY) { - if (this.isEnabled) { - let pointerScreenX = pageX - window.scrollX; - let pointerScreenY = pageY - window.scrollY; - let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY; - let 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()); - } - } - } - stop() { - if (this.isEnabled) { - this.isAnimating = false; // will stop animation - for (let scrollCache of this.scrollCaches) { - scrollCache.destroy(); - } - this.scrollCaches = null; - } - } - requestAnimation(now) { - this.msSinceRequest = now; - requestAnimationFrame(this.animate); - } - handleSide(edge, seconds) { - let { scrollCache } = edge; - let { edgeThreshold } = this; - let invDistance = edgeThreshold - edge.distance; - let velocity = // the closer to the edge, the faster we scroll - ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic - this.maxVelocity * seconds; - let 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 - computeBestEdge(left, top) { - let { edgeThreshold } = this; - let bestSide = null; - let scrollCaches = this.scrollCaches || []; - for (let scrollCache of scrollCaches) { - let rect = scrollCache.clientRect; - let leftDist = left - rect.left; - let rightDist = rect.right - left; - let topDist = top - rect.top; - let 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, name: 'top', distance: topDist }; - } - if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() && - (!bestSide || bestSide.distance > bottomDist)) { - bestSide = { scrollCache, name: 'bottom', distance: bottomDist }; - } - /* - TODO: fix broken RTL scrolling. canScrollLeft always returning false - https://github.com/fullcalendar/fullcalendar/issues/4837 - */ - if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() && - (!bestSide || bestSide.distance > leftDist)) { - bestSide = { scrollCache, name: 'left', distance: leftDist }; - } - if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() && - (!bestSide || bestSide.distance > rightDist)) { - bestSide = { scrollCache, name: 'right', distance: rightDist }; - } - } - } - return bestSide; - } - buildCaches(scrollStartEl) { - return this.queryScrollEls(scrollStartEl).map((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 - }); - } - queryScrollEls(scrollStartEl) { - let els = []; - for (let query of this.scrollQuery) { - if (typeof query === 'object') { - els.push(query); - } - else { - /* - TODO: in the future, always have auto-scroll happen on element where current Hit came from - Ticket: https://github.com/fullcalendar/fullcalendar/issues/4593 - */ - els.push(...Array.prototype.slice.call(scrollStartEl.getRootNode().querySelectorAll(query))); - } - } - return els; - } - } - - /* - 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 - */ - class FeaturefulElementDragging extends internal.ElementDragging { - constructor(containerEl, selector) { - super(containerEl); - 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 = (ev) => { - if (!this.isDragging) { // so new drag doesn't happen while revert animation is going - this.isInteracting = true; - this.isDelayEnded = false; - this.isDistanceSurpassed = false; - internal.preventSelection(document.body); - internal.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 = (ev) => { - if (this.isInteracting) { - this.emitter.trigger('pointermove', ev); - if (!this.isDistanceSurpassed) { - let minDistance = this.minDistance; - let distanceSq; // current distance from the origin, squared - let { deltaX, deltaY } = ev; - 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 = (ev) => { - if (this.isInteracting) { - this.isInteracting = false; - internal.allowSelection(document.body); - internal.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; - } - } - }; - let 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(); - } - destroy() { - 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({}); - } - startDelay(ev) { - if (typeof this.delay === 'number') { - this.delayTimeoutId = setTimeout(() => { - this.delayTimeoutId = null; - this.handleDelayEnd(ev); - }, this.delay); // not assignable to number! - } - else { - this.handleDelayEnd(ev); - } - } - handleDelayEnd(ev) { - this.isDelayEnded = true; - this.tryStartDrag(ev); - } - handleDistanceSurpassed(ev) { - this.isDistanceSurpassed = true; - this.tryStartDrag(ev); - } - tryStartDrag(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(); - } - } - } - } - tryStopDrag(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)); - } - stopDrag(ev) { - this.isDragging = false; - this.emitter.trigger('dragend', ev); - } - // fill in the implementations... - setIgnoreMove(bool) { - this.pointer.shouldIgnoreMove = bool; - } - setMirrorIsVisible(bool) { - this.mirror.setIsVisible(bool); - } - setMirrorNeedsRevert(bool) { - this.mirrorNeedsRevert = bool; - } - setAutoScrollEnabled(bool) { - this.autoScroller.isEnabled = bool; - } - } - - /* - 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. - */ - class OffsetTracker { - constructor(el) { - this.el = el; - this.origRect = internal.computeRect(el); - // will work fine for divs that have overflow:hidden - this.scrollCaches = internal.getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true)); - } - destroy() { - for (let scrollCache of this.scrollCaches) { - scrollCache.destroy(); - } - } - computeLeft() { - let left = this.origRect.left; - for (let scrollCache of this.scrollCaches) { - left += scrollCache.origScrollLeft - scrollCache.getScrollLeft(); - } - return left; - } - computeTop() { - let top = this.origRect.top; - for (let scrollCache of this.scrollCaches) { - top += scrollCache.origScrollTop - scrollCache.getScrollTop(); - } - return top; - } - isWithinClipping(pageX, pageY) { - let point = { left: pageX, top: pageY }; - for (let scrollCache of this.scrollCaches) { - if (!isIgnoredClipping(scrollCache.getEventTarget()) && - !internal.pointInsideRect(point, scrollCache.clientRect)) { - return false; - } - } - return true; - } - } - // certain clipping containers should never constrain interactions, like and - // https://github.com/fullcalendar/fullcalendar/issues/3615 - function isIgnoredClipping(node) { - let 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 - */ - class HitDragging { - constructor(dragging, droppableStore) { - // 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.disablePointCheck = false; - this.initialHit = null; - this.movingHit = null; - this.finalHit = null; // won't ever be populated if shouldIgnoreMove - this.handlePointerDown = (ev) => { - let { dragging } = this; - 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 = (ev) => { - this.emitter.trigger('dragstart', ev); - this.handleMove(ev, true); // force = fire even if initially null - }; - this.handleDragMove = (ev) => { - this.emitter.trigger('dragmove', ev); - this.handleMove(ev); - }; - this.handlePointerUp = (ev) => { - this.releaseHits(); - this.emitter.trigger('pointerup', ev); - }; - this.handleDragEnd = (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 internal.Emitter(); - } - // sets initialHit - // sets coordAdjust - processFirstCoord(ev) { - let origPoint = { left: ev.pageX, top: ev.pageY }; - let adjustedPoint = origPoint; - let subjectEl = ev.subjectEl; - let subjectRect; - if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot - subjectRect = internal.computeRect(subjectEl); - adjustedPoint = internal.constrainPoint(adjustedPoint, subjectRect); - } - let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top); - if (initialHit) { - if (this.useSubjectCenter && subjectRect) { - let slicedSubjectRect = internal.intersectRects(subjectRect, initialHit.rect); - if (slicedSubjectRect) { - adjustedPoint = internal.getRectCenter(slicedSubjectRect); - } - } - this.coordAdjust = internal.diffPoints(adjustedPoint, origPoint); - } - else { - this.coordAdjust = { left: 0, top: 0 }; - } - } - handleMove(ev, forceHandle) { - let 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); - } - } - prepareHits() { - this.offsetTrackers = internal.mapHash(this.droppableStore, (interactionSettings) => { - interactionSettings.component.prepareHits(); - return new OffsetTracker(interactionSettings.el); - }); - } - releaseHits() { - let { offsetTrackers } = this; - for (let id in offsetTrackers) { - offsetTrackers[id].destroy(); - } - this.offsetTrackers = {}; - } - queryHitForOffset(offsetLeft, offsetTop) { - let { droppableStore, offsetTrackers } = this; - let bestHit = null; - for (let id in droppableStore) { - let component = droppableStore[id].component; - let offsetTracker = offsetTrackers[id]; - if (offsetTracker && // wasn't destroyed mid-drag - offsetTracker.isWithinClipping(offsetLeft, offsetTop)) { - let originLeft = offsetTracker.computeLeft(); - let originTop = offsetTracker.computeTop(); - let positionLeft = offsetLeft - originLeft; - let positionTop = offsetTop - originTop; - let { origRect } = offsetTracker; - let width = origRect.right - origRect.left; - let height = origRect.bottom - origRect.top; - if ( - // must be within the element's bounds - positionLeft >= 0 && positionLeft < width && - positionTop >= 0 && positionTop < height) { - let hit = component.queryHit(positionLeft, positionTop, width, height); - if (hit && ( - // make sure the hit is within activeRange, meaning it's not a dead cell - internal.rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) && - // Ensure the component we are querying for the hit is accessibly my the pointer - // Prevents obscured calendars (ex: under a modal dialog) from accepting hit - // https://github.com/fullcalendar/fullcalendar/issues/5026 - (this.disablePointCheck || - offsetTracker.el.contains(offsetTracker.el.getRootNode().elementFromPoint( - // add-back origins to get coordinate relative to top-left of window viewport - positionLeft + originLeft - window.scrollX, positionTop + originTop - window.scrollY))) && - (!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; - } - } - function isHitsEqual(hit0, hit1) { - if (!hit0 && !hit1) { - return true; - } - if (Boolean(hit0) !== Boolean(hit1)) { - return false; - } - return internal.isDateSpansEqual(hit0.dateSpan, hit1.dateSpan); - } - - function buildDatePointApiWithContext(dateSpan, context) { - let props = {}; - for (let transform of context.pluginHooks.datePointTransforms) { - Object.assign(props, transform(dateSpan, context)); - } - Object.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. - */ - class DateClicking extends internal.Interaction { - constructor(settings) { - super(settings); - this.handlePointerDown = (pev) => { - let { dragging } = this; - let 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 = (ev) => { - let { component } = this; - let { pointer } = this.dragging; - if (!pointer.wasTouchScroll) { - let { initialHit, finalHit } = this.hitDragging; - if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) { - let { context } = component; - let arg = Object.assign(Object.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; - let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.interactionSettingsToStore(settings)); - hitDragging.emitter.on('pointerdown', this.handlePointerDown); - hitDragging.emitter.on('dragend', this.handleDragEnd); - } - destroy() { - this.dragging.destroy(); - } - } - - /* - 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. - */ - class DateSelecting extends internal.Interaction { - constructor(settings) { - super(settings); - this.dragSelection = null; - this.handlePointerDown = (ev) => { - let { component, dragging } = this; - let { options } = component.context; - let 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 = (ev) => { - this.component.context.calendarApi.unselect(ev); // unselect previous selections - }; - this.handleHitUpdate = (hit, isFinal) => { - let { context } = this.component; - let dragSelection = null; - let isInvalid = false; - if (hit) { - let initialHit = this.hitDragging.initialHit; - let disallowed = hit.componentId === initialHit.componentId - && this.isHitComboAllowed - && !this.isHitComboAllowed(initialHit, hit); - if (!disallowed) { - dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers); - } - if (!dragSelection || !internal.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) { - internal.enableCursor(); - } - else { - internal.disableCursor(); - } - if (!isFinal) { - this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging - } - }; - this.handlePointerUp = (pev) => { - if (this.dragSelection) { - // selection is already rendered, so just need to report selection - internal.triggerDateSelect(this.dragSelection, pev, this.component.context); - this.dragSelection = null; - } - }; - let { component } = settings; - let { options } = component.context; - let dragging = this.dragging = new FeaturefulElementDragging(settings.el); - dragging.touchScrollAllowed = false; - dragging.minDistance = options.selectMinDistance || 0; - dragging.autoScroller.isEnabled = options.dragScroll; - let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.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); - } - destroy() { - this.dragging.destroy(); - } - } - function getComponentTouchDelay$1(component) { - let { options } = component.context; - let delay = options.selectLongPressDelay; - if (delay == null) { - delay = options.longPressDelay; - } - return delay; - } - function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) { - let dateSpan0 = hit0.dateSpan; - let dateSpan1 = hit1.dateSpan; - let ms = [ - dateSpan0.range.start, - dateSpan0.range.end, - dateSpan1.range.start, - dateSpan1.range.end, - ]; - ms.sort(internal.compareNumbers); - let props = {}; - for (let transformer of dateSelectionTransformers) { - let res = transformer(hit0, hit1); - if (res === false) { - return null; - } - if (res) { - Object.assign(props, res); - } - } - props.range = { start: ms[0], end: ms[3] }; - props.allDay = dateSpan0.allDay; - return props; - } - - class EventDragging extends internal.Interaction { - constructor(settings) { - super(settings); - // 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 = (ev) => { - let origTarget = ev.origEvent.target; - let { component, dragging } = this; - let { mirror } = dragging; - let { options } = component.context; - let initialContext = component.context; - this.subjectEl = ev.subjectEl; - let subjectSeg = this.subjectSeg = internal.getElSeg(ev.subjectEl); - let eventRange = this.eventRange = subjectSeg.eventRange; - let eventInstanceId = eventRange.instance.instanceId; - this.relevantEvents = internal.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 = internal.elementClosest(origTarget, '.fc'); - } - mirror.revertDuration = options.dragRevertDuration; - let isValid = component.isValidSegDownEl(origTarget) && - !internal.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 = (ev) => { - let initialContext = this.component.context; - let eventRange = this.eventRange; - let 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 }); - } - } - 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 internal.EventImpl(initialContext, eventRange.def, eventRange.instance), - jsEvent: ev.origEvent, - view: initialContext.viewApi, - }); - } - }; - this.handleHitUpdate = (hit, isFinal) => { - if (!this.isDragging) { - return; - } - let relevantEvents = this.relevantEvents; - let initialHit = this.hitDragging.initialHit; - let initialContext = this.component.context; - // states based on new hit - let receivingContext = null; - let mutation = null; - let mutatedRelevantEvents = null; - let isInvalid = false; - let interaction = { - affectedEvents: relevantEvents, - mutatedEvents: internal.createEmptyEventStore(), - isEvent: true, - }; - if (hit) { - receivingContext = hit.context; - let receivingOptions = receivingContext.options; - if (initialContext === receivingContext || - (receivingOptions.editable && receivingOptions.droppable)) { - mutation = computeEventMutation(initialHit, hit, this.eventRange.instance.range.start, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers); - if (mutation) { - mutatedRelevantEvents = internal.applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext); - interaction.mutatedEvents = mutatedRelevantEvents; - if (!internal.isInteractionValid(interaction, hit.dateProfile, receivingContext)) { - isInvalid = true; - mutation = null; - mutatedRelevantEvents = null; - interaction.mutatedEvents = internal.createEmptyEventStore(); - } - } - } - else { - receivingContext = null; - } - } - this.displayDrag(receivingContext, interaction); - if (!isInvalid) { - internal.enableCursor(); - } - else { - internal.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 || !this.subjectEl.getRootNode().querySelector('.fc-event-mirror')); - // assign states based on new hit - this.receivingContext = receivingContext; - this.validMutation = mutation; - this.mutatedRelevantEvents = mutatedRelevantEvents; - } - }; - this.handlePointerUp = () => { - if (!this.isDragging) { - this.cleanup(); // because handleDragEnd won't fire - } - }; - this.handleDragEnd = (ev) => { - if (this.isDragging) { - let initialContext = this.component.context; - let initialView = initialContext.viewApi; - let { receivingContext, validMutation } = this; - let eventDef = this.eventRange.def; - let eventInstance = this.eventRange.instance; - let eventApi = new internal.EventImpl(initialContext, eventDef, eventInstance); - let relevantEvents = this.relevantEvents; - let mutatedRelevantEvents = this.mutatedRelevantEvents; - let { finalHit } = this.hitDragging; - this.clearDrag(); // must happen after revert animation - initialContext.emitter.trigger('eventDragStop', { - el: this.subjectEl, - event: eventApi, - jsEvent: ev.origEvent, - view: initialView, - }); - if (validMutation) { - // dropped within same calendar - if (receivingContext === initialContext) { - let updatedEventApi = new internal.EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null); - initialContext.dispatch({ - type: 'MERGE_EVENTS', - eventStore: mutatedRelevantEvents, - }); - let eventChangeArg = { - oldEvent: eventApi, - event: updatedEventApi, - relatedEvents: internal.buildEventApis(mutatedRelevantEvents, initialContext, eventInstance), - revert() { - initialContext.dispatch({ - type: 'MERGE_EVENTS', - eventStore: relevantEvents, // the pre-change data - }); - }, - }; - let transformed = {}; - for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) { - Object.assign(transformed, transformer(validMutation, initialContext)); - } - initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView })); - initialContext.emitter.trigger('eventChange', eventChangeArg); - // dropped in different calendar - } - else if (receivingContext) { - let eventRemoveArg = { - event: eventApi, - relatedEvents: internal.buildEventApis(relevantEvents, initialContext, eventInstance), - revert() { - initialContext.dispatch({ - type: 'MERGE_EVENTS', - eventStore: relevantEvents, - }); - }, - }; - initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView })); - initialContext.dispatch({ - type: 'REMOVE_EVENTS', - eventStore: relevantEvents, - }); - initialContext.emitter.trigger('eventRemove', eventRemoveArg); - let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId]; - let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId]; - let addedEventApi = new internal.EventImpl(receivingContext, addedEventDef, addedEventInstance); - receivingContext.dispatch({ - type: 'MERGE_EVENTS', - eventStore: mutatedRelevantEvents, - }); - let eventAddArg = { - event: addedEventApi, - relatedEvents: internal.buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance), - revert() { - receivingContext.dispatch({ - type: 'REMOVE_EVENTS', - eventStore: mutatedRelevantEvents, - }); - }, - }; - receivingContext.emitter.trigger('eventAdd', eventAddArg); - if (ev.isTouch) { - receivingContext.dispatch({ - type: 'SELECT_EVENT', - eventInstanceId: eventInstance.instanceId, - }); - } - receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi })); - receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi })); - } - } - else { - initialContext.emitter.trigger('_noEventDrop'); - } - } - this.cleanup(); - }; - let { component } = this; - let { options } = component.context; - let dragging = this.dragging = new FeaturefulElementDragging(settings.el); - dragging.pointer.selector = EventDragging.SELECTOR; - dragging.touchScrollAllowed = false; - dragging.autoScroller.isEnabled = options.dragScroll; - let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.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); - } - destroy() { - this.dragging.destroy(); - } - // render a drag state on the next receivingCalendar - displayDrag(nextContext, state) { - let initialContext = this.component.context; - let 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: internal.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 }); - } - } - clearDrag() { - let initialCalendar = this.component.context; - let { receivingContext } = this; - 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' }); - } - } - cleanup() { - 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'; - function computeEventMutation(hit0, hit1, eventInstanceStart, massagers) { - let dateSpan0 = hit0.dateSpan; - let dateSpan1 = hit1.dateSpan; - let date0 = dateSpan0.range.start; - let date1 = dateSpan1.range.start; - let 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 = internal.startOfDay(eventInstanceStart); - } - else { - // Moving from allDate->timed - // Doesn't matter where on the event the drag began, mutate the event's start-date to date1 - date0 = eventInstanceStart; - } - } - let delta = internal.diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ? - hit0.largeUnit : - null); - if (delta.milliseconds) { // has hours/minutes/seconds - standardProps.allDay = false; - } - let mutation = { - datesDelta: delta, - standardProps, - }; - for (let massager of massagers) { - massager(mutation, hit0, hit1); - } - return mutation; - } - function getComponentTouchDelay(component) { - let { options } = component.context; - let delay = options.eventLongPressDelay; - if (delay == null) { - delay = options.longPressDelay; - } - return delay; - } - - class EventResizing extends internal.Interaction { - constructor(settings) { - super(settings); - // 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 = (ev) => { - let { component } = this; - let segEl = this.querySegEl(ev); - let seg = internal.getElSeg(segEl); - let 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 = (ev) => { - let { context } = this.component; - let eventRange = this.eventRange; - this.relevantEvents = internal.getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId); - let segEl = this.querySegEl(ev); - this.draggingSegEl = segEl; - this.draggingSeg = internal.getElSeg(segEl); - context.calendarApi.unselect(); - context.emitter.trigger('eventResizeStart', { - el: segEl, - event: new internal.EventImpl(context, eventRange.def, eventRange.instance), - jsEvent: ev.origEvent, - view: context.viewApi, - }); - }; - this.handleHitUpdate = (hit, isFinal, ev) => { - let { context } = this.component; - let relevantEvents = this.relevantEvents; - let initialHit = this.hitDragging.initialHit; - let eventInstance = this.eventRange.instance; - let mutation = null; - let mutatedRelevantEvents = null; - let isInvalid = false; - let interaction = { - affectedEvents: relevantEvents, - mutatedEvents: internal.createEmptyEventStore(), - isEvent: true, - }; - if (hit) { - let 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 = internal.applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context); - interaction.mutatedEvents = mutatedRelevantEvents; - if (!internal.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) { - internal.enableCursor(); - } - else { - internal.disableCursor(); - } - if (!isFinal) { - if (mutation && isHitsEqual(initialHit, hit)) { - mutation = null; - } - this.validMutation = mutation; - this.mutatedRelevantEvents = mutatedRelevantEvents; - } - }; - this.handleDragEnd = (ev) => { - let { context } = this.component; - let eventDef = this.eventRange.def; - let eventInstance = this.eventRange.instance; - let eventApi = new internal.EventImpl(context, eventDef, eventInstance); - let relevantEvents = this.relevantEvents; - let mutatedRelevantEvents = this.mutatedRelevantEvents; - context.emitter.trigger('eventResizeStop', { - el: this.draggingSegEl, - event: eventApi, - jsEvent: ev.origEvent, - view: context.viewApi, - }); - if (this.validMutation) { - let updatedEventApi = new internal.EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null); - context.dispatch({ - type: 'MERGE_EVENTS', - eventStore: mutatedRelevantEvents, - }); - let eventChangeArg = { - oldEvent: eventApi, - event: updatedEventApi, - relatedEvents: internal.buildEventApis(mutatedRelevantEvents, context, eventInstance), - revert() { - context.dispatch({ - type: 'MERGE_EVENTS', - eventStore: relevantEvents, // the pre-change events - }); - }, - }; - context.emitter.trigger('eventResize', Object.assign(Object.assign({}, eventChangeArg), { el: this.draggingSegEl, startDelta: this.validMutation.startDelta || internal.createDuration(0), endDelta: this.validMutation.endDelta || internal.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 - }; - let { component } = settings; - let dragging = this.dragging = new FeaturefulElementDragging(settings.el); - dragging.pointer.selector = '.fc-event-resizer'; - dragging.touchScrollAllowed = false; - dragging.autoScroller.isEnabled = component.context.options.dragScroll; - let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.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); - } - destroy() { - this.dragging.destroy(); - } - querySegEl(ev) { - return internal.elementClosest(ev.subjectEl, '.fc-event'); - } - } - function computeMutation(hit0, hit1, isFromStart, instanceRange) { - let dateEnv = hit0.context.dateEnv; - let date0 = hit0.dateSpan.range.start; - let date1 = hit1.dateSpan.range.start; - let delta = internal.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; - } - - class UnselectAuto { - constructor(context) { - 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 = (selectInfo) => { - if (selectInfo.jsEvent) { - this.isRecentPointerDateSelect = true; - } - }; - this.onDocumentPointerDown = (pev) => { - let unselectCancel = this.context.options.unselectCancel; - let downEl = internal.getEventTargetViaRoot(pev.origEvent); - this.matchesCancel = !!internal.elementClosest(downEl, unselectCancel); - this.matchesEvent = !!internal.elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event? - }; - this.onDocumentPointerUp = (pev) => { - let { context } = this; - let { documentPointer } = this; - let 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? - ) { - let 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; - }; - let 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); - } - destroy() { - this.context.emitter.off('select', this.onSelect); - this.documentPointer.destroy(); - } - } - - const OPTION_REFINERS = { - fixedMirrorParent: internal.identity, - }; - const LISTENER_REFINERS = { - dateClick: internal.identity, - eventDragStart: internal.identity, - eventDragStop: internal.identity, - eventDrop: internal.identity, - eventResizeStart: internal.identity, - eventResizeStop: internal.identity, - eventResize: internal.identity, - drop: internal.identity, - eventReceive: internal.identity, - eventLeave: internal.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. - */ - class ExternalElementDragging { - constructor(dragging, suppliedDragMeta) { - this.receivingContext = null; - this.droppableEvent = null; // will exist for all drags, even if create:false - this.suppliedDragMeta = null; - this.dragMeta = null; - this.handleDragStart = (ev) => { - this.dragMeta = this.buildDragMeta(ev.subjectEl); - }; - this.handleHitUpdate = (hit, isFinal, ev) => { - let { dragging } = this.hitDragging; - let receivingContext = null; - let droppableEvent = null; - let isInvalid = false; - let interaction = { - affectedEvents: internal.createEmptyEventStore(), - mutatedEvents: internal.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 = internal.eventTupleToStore(droppableEvent); - isInvalid = !internal.isInteractionValid(interaction, hit.dateProfile, receivingContext); - if (isInvalid) { - interaction.mutatedEvents = internal.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) { - internal.enableCursor(); - } - else { - internal.disableCursor(); - } - if (!isFinal) { - dragging.setMirrorNeedsRevert(!droppableEvent); - this.receivingContext = receivingContext; - this.droppableEvent = droppableEvent; - } - }; - this.handleDragEnd = (pev) => { - let { receivingContext, droppableEvent } = this; - this.clearDrag(); - if (receivingContext && droppableEvent) { - let finalHit = this.hitDragging.finalHit; - let finalView = finalHit.context.viewApi; - let dragMeta = this.dragMeta; - receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView })); - if (dragMeta.create) { - let addingEvents = internal.eventTupleToStore(droppableEvent); - receivingContext.dispatch({ - type: 'MERGE_EVENTS', - eventStore: addingEvents, - }); - if (pev.isTouch) { - receivingContext.dispatch({ - type: 'SELECT_EVENT', - eventInstanceId: droppableEvent.instance.instanceId, - }); - } - // signal that an external event landed - receivingContext.emitter.trigger('eventReceive', { - event: new internal.EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance), - relatedEvents: [], - revert() { - receivingContext.dispatch({ - type: 'REMOVE_EVENTS', - eventStore: addingEvents, - }); - }, - draggedEl: pev.subjectEl, - view: finalView, - }); - } - } - this.receivingContext = null; - this.droppableEvent = null; - }; - let hitDragging = this.hitDragging = new HitDragging(dragging, internal.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; - } - buildDragMeta(subjectEl) { - if (typeof this.suppliedDragMeta === 'object') { - return internal.parseDragMeta(this.suppliedDragMeta); - } - if (typeof this.suppliedDragMeta === 'function') { - return internal.parseDragMeta(this.suppliedDragMeta(subjectEl)); - } - return getDragMetaFromEl(subjectEl); - } - displayDrag(nextContext, state) { - let prevContext = this.receivingContext; - if (prevContext && prevContext !== nextContext) { - prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); - } - if (nextContext) { - nextContext.dispatch({ type: 'SET_EVENT_DRAG', state }); - } - } - clearDrag() { - if (this.receivingContext) { - this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' }); - } - } - canDropElOnCalendar(el, receivingContext) { - let dropAccept = receivingContext.options.dropAccept; - if (typeof dropAccept === 'function') { - return dropAccept.call(receivingContext.calendarApi, el); - } - if (typeof dropAccept === 'string' && dropAccept) { - return Boolean(internal.elementMatches(el, dropAccept)); - } - return true; - } - } - // Utils for computing event store from the DragMeta - // ---------------------------------------------------------------------------------------------------- - function computeEventForDateSpan(dateSpan, dragMeta, context) { - let defProps = Object.assign({}, dragMeta.leftoverProps); - for (let transform of context.pluginHooks.externalDefTransforms) { - Object.assign(defProps, transform(dateSpan, dragMeta)); - } - let { refined, extra } = internal.refineEventDef(defProps, context); - let def = internal.parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd - context); - let 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); - } - let end = dragMeta.duration ? - context.dateEnv.add(start, dragMeta.duration) : - internal.getDefaultEventEnd(dateSpan.allDay, start, context); - let instance = internal.createEventInstance(def.defId, { start, end }); - return { def, instance }; - } - // Utils for extracting data from element - // ---------------------------------------------------------------------------------------------------- - function getDragMetaFromEl(el) { - let str = getEmbeddedElData(el, 'event'); - let obj = str ? - JSON.parse(str) : - { create: false }; // if no embedded data, assume no event creation - return internal.parseDragMeta(obj); - } - internal.config.dataAttrPrefix = ''; - function getEmbeddedElData(el, name) { - let prefix = internal.config.dataAttrPrefix; - let 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. - */ - class ExternalDraggable { - constructor(el, settings = {}) { - this.handlePointerDown = (ev) => { - let { dragging } = this; - let { minDistance, longPressDelay } = this.settings; - dragging.minDistance = - minDistance != null ? - minDistance : - (ev.isTouch ? 0 : internal.BASE_OPTION_DEFAULTS.eventDragMinDistance); - dragging.delay = - ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv - (longPressDelay != null ? longPressDelay : internal.BASE_OPTION_DEFAULTS.longPressDelay) : - 0; - }; - this.handleDragStart = (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; - let 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 - } - destroy() { - this.dragging.destroy(); - } - } - - /* - 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. - */ - class InferredElementDragging extends internal.ElementDragging { - constructor(containerEl) { - super(containerEl); - this.shouldIgnoreMove = false; - this.mirrorSelector = ''; - this.currentMirrorEl = null; - this.handlePointerDown = (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 = (ev) => { - if (!this.shouldIgnoreMove) { - this.emitter.trigger('dragmove', ev); - } - }; - this.handlePointerUp = (ev) => { - this.emitter.trigger('pointerup', ev); - if (!this.shouldIgnoreMove) { - // fire dragend right away. does not support a revert animation - this.emitter.trigger('dragend', ev); - } - }; - let pointer = this.pointer = new PointerDragging(containerEl); - pointer.emitter.on('pointerdown', this.handlePointerDown); - pointer.emitter.on('pointermove', this.handlePointerMove); - pointer.emitter.on('pointerup', this.handlePointerUp); - } - destroy() { - this.pointer.destroy(); - } - setIgnoreMove(bool) { - this.shouldIgnoreMove = bool; - } - setMirrorIsVisible(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 { - let mirrorEl = this.mirrorSelector - // TODO: somehow query FullCalendars WITHIN shadow-roots - ? document.querySelector(this.mirrorSelector) - : null; - if (mirrorEl) { - this.currentMirrorEl = mirrorEl; - mirrorEl.style.visibility = 'hidden'; - } - } - } - } - - /* - Bridges third-party drag-n-drop systems with FullCalendar. - Must be instantiated and destroyed by caller. - */ - class ThirdPartyDraggable { - constructor(containerOrSettings, settings) { - let 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 || {}); - } - let 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; - } - let externalDragging = new ExternalElementDragging(dragging, settings.eventData); - // The hit-detection system requires that the dnd-mirror-element be pointer-events:none, - // but this can't be guaranteed for third-party draggables, so disable - externalDragging.hitDragging.disablePointCheck = true; - } - destroy() { - this.dragging.destroy(); - } - } - - var plugin = core.createPlugin({ - name: '@fullcalendar/interaction', - componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing], - calendarInteractions: [UnselectAuto], - elementDraggingImpl: FeaturefulElementDragging, - optionRefiners: OPTION_REFINERS, - listenerRefiners: LISTENER_REFINERS, - }); - - core.globalPlugins.push(plugin); - - exports.Draggable = ExternalDraggable; - exports.ThirdPartyDraggable = ThirdPartyDraggable; - exports["default"] = plugin; - - Object.defineProperty(exports, '__esModule', { value: true }); - - return exports; - -})({}, FullCalendar, FullCalendar.Internal); diff --git a/public/js/fullcalendar/packages/interaction/index.global.min.js b/public/js/fullcalendar/packages/interaction/index.global.min.js deleted file mode 100644 index 1522b55..0000000 --- a/public/js/fullcalendar/packages/interaction/index.global.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! -FullCalendar Interaction Plugin v6.1.17 -Docs & License: https://fullcalendar.io/docs/editable -(c) 2024 Adam Shaw -*/ -FullCalendar.Interaction=function(t,e,i){"use strict";i.config.touchMouseIgnoreWait=500;let n=0,s=0,r=!1;class o{constructor(t){this.subjectEl=null,this.selector="",this.handleSelector="",this.shouldIgnoreMove=!1,this.shouldWatchScroll=!0,this.isDragging=!1,this.isTouchDragging=!1,this.wasTouchScroll=!1,this.handleMouseDown=t=>{if(!this.shouldIgnoreMouse()&&function(t){return 0===t.button&&!t.ctrlKey}(t)&&this.tryStart(t)){let e=this.createEventFromMouse(t,!0);this.emitter.trigger("pointerdown",e),this.initScrollWatch(e),this.shouldIgnoreMove||document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}},this.handleMouseMove=t=>{let e=this.createEventFromMouse(t);this.recordCoords(e),this.emitter.trigger("pointermove",e)},this.handleMouseUp=t=>{document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),this.emitter.trigger("pointerup",this.createEventFromMouse(t)),this.cleanup()},this.handleTouchStart=t=>{if(this.tryStart(t)){this.isTouchDragging=!0;let e=this.createEventFromTouch(t,!0);this.emitter.trigger("pointerdown",e),this.initScrollWatch(e);let i=t.target;this.shouldIgnoreMove||i.addEventListener("touchmove",this.handleTouchMove),i.addEventListener("touchend",this.handleTouchEnd),i.addEventListener("touchcancel",this.handleTouchEnd),window.addEventListener("scroll",this.handleTouchScroll,!0)}},this.handleTouchMove=t=>{let e=this.createEventFromTouch(t);this.recordCoords(e),this.emitter.trigger("pointermove",e)},this.handleTouchEnd=t=>{if(this.isDragging){let e=t.target;e.removeEventListener("touchmove",this.handleTouchMove),e.removeEventListener("touchend",this.handleTouchEnd),e.removeEventListener("touchcancel",this.handleTouchEnd),window.removeEventListener("scroll",this.handleTouchScroll,!0),this.emitter.trigger("pointerup",this.createEventFromTouch(t)),this.cleanup(),this.isTouchDragging=!1,n+=1,setTimeout(()=>{n-=1},i.config.touchMouseIgnoreWait)}},this.handleTouchScroll=()=>{this.wasTouchScroll=!0},this.handleScroll=t=>{if(!this.shouldIgnoreMove){let e=window.scrollX-this.prevScrollX+this.prevPageX,i=window.scrollY-this.prevScrollY+this.prevPageY;this.emitter.trigger("pointermove",{origEvent:t,isTouch:this.isTouchDragging,subjectEl:this.subjectEl,pageX:e,pageY:i,deltaX:e-this.origPageX,deltaY:i-this.origPageY})}},this.containerEl=t,this.emitter=new i.Emitter,t.addEventListener("mousedown",this.handleMouseDown),t.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),s+=1,1===s&&window.addEventListener("touchmove",l,{passive:!1})}destroy(){this.containerEl.removeEventListener("mousedown",this.handleMouseDown),this.containerEl.removeEventListener("touchstart",this.handleTouchStart,{passive:!0}),s-=1,s||window.removeEventListener("touchmove",l,{passive:!1})}tryStart(t){let e=this.querySubjectEl(t),n=t.target;return!(!e||this.handleSelector&&!i.elementClosest(n,this.handleSelector))&&(this.subjectEl=e,this.isDragging=!0,this.wasTouchScroll=!1,!0)}cleanup(){r=!1,this.isDragging=!1,this.subjectEl=null,this.destroyScrollWatch()}querySubjectEl(t){return this.selector?i.elementClosest(t.target,this.selector):this.containerEl}shouldIgnoreMouse(){return n||this.isTouchDragging}cancelTouchScroll(){this.isDragging&&(r=!0)}initScrollWatch(t){this.shouldWatchScroll&&(this.recordCoords(t),window.addEventListener("scroll",this.handleScroll,!0))}recordCoords(t){this.shouldWatchScroll&&(this.prevPageX=t.pageX,this.prevPageY=t.pageY,this.prevScrollX=window.scrollX,this.prevScrollY=window.scrollY)}destroyScrollWatch(){this.shouldWatchScroll&&window.removeEventListener("scroll",this.handleScroll,!0)}createEventFromMouse(t,e){let i=0,n=0;return e?(this.origPageX=t.pageX,this.origPageY=t.pageY):(i=t.pageX-this.origPageX,n=t.pageY-this.origPageY),{origEvent:t,isTouch:!1,subjectEl:this.subjectEl,pageX:t.pageX,pageY:t.pageY,deltaX:i,deltaY:n}}createEventFromTouch(t,e){let i,n,s=t.touches,r=0,o=0;return s&&s.length?(i=s[0].pageX,n=s[0].pageY):(i=t.pageX,n=t.pageY),e?(this.origPageX=i,this.origPageY=n):(r=i-this.origPageX,o=n-this.origPageY),{origEvent:t,isTouch:!0,subjectEl:this.subjectEl,pageX:i,pageY:n,deltaX:r,deltaY:o}}}function l(t){r&&t.preventDefault()}class a{constructor(){this.isVisible=!1,this.sourceEl=null,this.mirrorEl=null,this.sourceElRect=null,this.parentNode=document.body,this.zIndex=9999,this.revertDuration=0}start(t,e,i){this.sourceEl=t,this.sourceElRect=this.sourceEl.getBoundingClientRect(),this.origScreenX=e-window.scrollX,this.origScreenY=i-window.scrollY,this.deltaX=0,this.deltaY=0,this.updateElPosition()}handleMove(t,e){this.deltaX=t-window.scrollX-this.origScreenX,this.deltaY=e-window.scrollY-this.origScreenY,this.updateElPosition()}setIsVisible(t){t?this.isVisible||(this.mirrorEl&&(this.mirrorEl.style.display=""),this.isVisible=t,this.updateElPosition()):this.isVisible&&(this.mirrorEl&&(this.mirrorEl.style.display="none"),this.isVisible=t)}stop(t,e){let i=()=>{this.cleanup(),e()};t&&this.mirrorEl&&this.isVisible&&this.revertDuration&&(this.deltaX||this.deltaY)?this.doRevertAnimation(i,this.revertDuration):setTimeout(i,0)}doRevertAnimation(t,e){let n=this.mirrorEl,s=this.sourceEl.getBoundingClientRect();n.style.transition="top "+e+"ms,left "+e+"ms",i.applyStyle(n,{left:s.left,top:s.top}),i.whenTransitionDone(n,()=>{n.style.transition="",t()})}cleanup(){this.mirrorEl&&(i.removeElement(this.mirrorEl),this.mirrorEl=null),this.sourceEl=null}updateElPosition(){this.sourceEl&&this.isVisible&&i.applyStyle(this.getMirrorEl(),{left:this.sourceElRect.left+this.deltaX,top:this.sourceElRect.top+this.deltaY})}getMirrorEl(){let t=this.sourceElRect,e=this.mirrorEl;return e||(e=this.mirrorEl=this.sourceEl.cloneNode(!0),e.style.userSelect="none",e.style.webkitUserSelect="none",e.style.pointerEvents="none",e.classList.add("fc-event-dragging"),i.applyStyle(e,{position:"fixed",zIndex:this.zIndex,visibility:"",boxSizing:"border-box",width:t.right-t.left,height:t.bottom-t.top,right:"auto",bottom:"auto",margin:0}),this.parentNode.appendChild(e)),e}}class h extends i.ScrollController{constructor(t,e){super(),this.handleScroll=()=>{this.scrollTop=this.scrollController.getScrollTop(),this.scrollLeft=this.scrollController.getScrollLeft(),this.handleScrollChange()},this.scrollController=t,this.doesListening=e,this.scrollTop=this.origScrollTop=t.getScrollTop(),this.scrollLeft=this.origScrollLeft=t.getScrollLeft(),this.scrollWidth=t.getScrollWidth(),this.scrollHeight=t.getScrollHeight(),this.clientWidth=t.getClientWidth(),this.clientHeight=t.getClientHeight(),this.clientRect=this.computeClientRect(),this.doesListening&&this.getEventTarget().addEventListener("scroll",this.handleScroll)}destroy(){this.doesListening&&this.getEventTarget().removeEventListener("scroll",this.handleScroll)}getScrollTop(){return this.scrollTop}getScrollLeft(){return this.scrollLeft}setScrollTop(t){this.scrollController.setScrollTop(t),this.doesListening||(this.scrollTop=Math.max(Math.min(t,this.getMaxScrollTop()),0),this.handleScrollChange())}setScrollLeft(t){this.scrollController.setScrollLeft(t),this.doesListening||(this.scrollLeft=Math.max(Math.min(t,this.getMaxScrollLeft()),0),this.handleScrollChange())}getClientWidth(){return this.clientWidth}getClientHeight(){return this.clientHeight}getScrollWidth(){return this.scrollWidth}getScrollHeight(){return this.scrollHeight}handleScrollChange(){}}class c extends h{constructor(t,e){super(new i.ElementScrollController(t),e)}getEventTarget(){return this.scrollController.el}computeClientRect(){return i.computeInnerRect(this.scrollController.el)}}class d extends h{constructor(t){super(new i.WindowScrollController,t)}getEventTarget(){return window}computeClientRect(){return{left:this.scrollLeft,right:this.scrollLeft+this.clientWidth,top:this.scrollTop,bottom:this.scrollTop+this.clientHeight}}handleScrollChange(){this.clientRect=this.computeClientRect()}}const g="function"==typeof performance?performance.now:Date.now;class u{constructor(){this.isEnabled=!0,this.scrollQuery=[window,".fc-scroller"],this.edgeThreshold=50,this.maxVelocity=300,this.pointerScreenX=null,this.pointerScreenY=null,this.isAnimating=!1,this.scrollCaches=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.animate=()=>{if(this.isAnimating){let t=this.computeBestEdge(this.pointerScreenX+window.scrollX,this.pointerScreenY+window.scrollY);if(t){let e=g();this.handleSide(t,(e-this.msSinceRequest)/1e3),this.requestAnimation(e)}else this.isAnimating=!1}}}start(t,e,i){this.isEnabled&&(this.scrollCaches=this.buildCaches(i),this.pointerScreenX=null,this.pointerScreenY=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.handleMove(t,e))}handleMove(t,e){if(this.isEnabled){let i=t-window.scrollX,n=e-window.scrollY,s=null===this.pointerScreenY?0:n-this.pointerScreenY,r=null===this.pointerScreenX?0:i-this.pointerScreenX;s<0?this.everMovedUp=!0:s>0&&(this.everMovedDown=!0),r<0?this.everMovedLeft=!0:r>0&&(this.everMovedRight=!0),this.pointerScreenX=i,this.pointerScreenY=n,this.isAnimating||(this.isAnimating=!0,this.requestAnimation(g()))}}stop(){if(this.isEnabled){this.isAnimating=!1;for(let t of this.scrollCaches)t.destroy();this.scrollCaches=null}}requestAnimation(t){this.msSinceRequest=t,requestAnimationFrame(this.animate)}handleSide(t,e){let{scrollCache:i}=t,{edgeThreshold:n}=this,s=n-t.distance,r=s*s/(n*n)*this.maxVelocity*e,o=1;switch(t.name){case"left":o=-1;case"right":i.setScrollLeft(i.getScrollLeft()+r*o);break;case"top":o=-1;case"bottom":i.setScrollTop(i.getScrollTop()+r*o)}}computeBestEdge(t,e){let{edgeThreshold:i}=this,n=null,s=this.scrollCaches||[];for(let r of s){let s=r.clientRect,o=t-s.left,l=s.right-t,a=e-s.top,h=s.bottom-e;o>=0&&l>=0&&a>=0&&h>=0&&(a<=i&&this.everMovedUp&&r.canScrollUp()&&(!n||n.distance>a)&&(n={scrollCache:r,name:"top",distance:a}),h<=i&&this.everMovedDown&&r.canScrollDown()&&(!n||n.distance>h)&&(n={scrollCache:r,name:"bottom",distance:h}),o<=i&&this.everMovedLeft&&r.canScrollLeft()&&(!n||n.distance>o)&&(n={scrollCache:r,name:"left",distance:o}),l<=i&&this.everMovedRight&&r.canScrollRight()&&(!n||n.distance>l)&&(n={scrollCache:r,name:"right",distance:l}))}return n}buildCaches(t){return this.queryScrollEls(t).map(t=>t===window?new d(!1):new c(t,!1))}queryScrollEls(t){let e=[];for(let i of this.scrollQuery)"object"==typeof i?e.push(i):e.push(...Array.prototype.slice.call(t.getRootNode().querySelectorAll(i)));return e}}class p extends i.ElementDragging{constructor(t,e){super(t),this.containerEl=t,this.delay=null,this.minDistance=0,this.touchScrollAllowed=!0,this.mirrorNeedsRevert=!1,this.isInteracting=!1,this.isDragging=!1,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.delayTimeoutId=null,this.onPointerDown=t=>{this.isDragging||(this.isInteracting=!0,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,i.preventSelection(document.body),i.preventContextMenu(document.body),t.isTouch||t.origEvent.preventDefault(),this.emitter.trigger("pointerdown",t),this.isInteracting&&!this.pointer.shouldIgnoreMove&&(this.mirror.setIsVisible(!1),this.mirror.start(t.subjectEl,t.pageX,t.pageY),this.startDelay(t),this.minDistance||this.handleDistanceSurpassed(t)))},this.onPointerMove=t=>{if(this.isInteracting){if(this.emitter.trigger("pointermove",t),!this.isDistanceSurpassed){let e,i=this.minDistance,{deltaX:n,deltaY:s}=t;e=n*n+s*s,e>=i*i&&this.handleDistanceSurpassed(t)}this.isDragging&&("scroll"!==t.origEvent.type&&(this.mirror.handleMove(t.pageX,t.pageY),this.autoScroller.handleMove(t.pageX,t.pageY)),this.emitter.trigger("dragmove",t))}},this.onPointerUp=t=>{this.isInteracting&&(this.isInteracting=!1,i.allowSelection(document.body),i.allowContextMenu(document.body),this.emitter.trigger("pointerup",t),this.isDragging&&(this.autoScroller.stop(),this.tryStopDrag(t)),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null))};let n=this.pointer=new o(t);n.emitter.on("pointerdown",this.onPointerDown),n.emitter.on("pointermove",this.onPointerMove),n.emitter.on("pointerup",this.onPointerUp),e&&(n.selector=e),this.mirror=new a,this.autoScroller=new u}destroy(){this.pointer.destroy(),this.onPointerUp({})}startDelay(t){"number"==typeof this.delay?this.delayTimeoutId=setTimeout(()=>{this.delayTimeoutId=null,this.handleDelayEnd(t)},this.delay):this.handleDelayEnd(t)}handleDelayEnd(t){this.isDelayEnded=!0,this.tryStartDrag(t)}handleDistanceSurpassed(t){this.isDistanceSurpassed=!0,this.tryStartDrag(t)}tryStartDrag(t){this.isDelayEnded&&this.isDistanceSurpassed&&(this.pointer.wasTouchScroll&&!this.touchScrollAllowed||(this.isDragging=!0,this.mirrorNeedsRevert=!1,this.autoScroller.start(t.pageX,t.pageY,this.containerEl),this.emitter.trigger("dragstart",t),!1===this.touchScrollAllowed&&this.pointer.cancelTouchScroll()))}tryStopDrag(t){this.mirror.stop(this.mirrorNeedsRevert,this.stopDrag.bind(this,t))}stopDrag(t){this.isDragging=!1,this.emitter.trigger("dragend",t)}setIgnoreMove(t){this.pointer.shouldIgnoreMove=t}setMirrorIsVisible(t){this.mirror.setIsVisible(t)}setMirrorNeedsRevert(t){this.mirrorNeedsRevert=t}setAutoScrollEnabled(t){this.autoScroller.isEnabled=t}}class v{constructor(t){this.el=t,this.origRect=i.computeRect(t),this.scrollCaches=i.getClippingParents(t).map(t=>new c(t,!0))}destroy(){for(let t of this.scrollCaches)t.destroy()}computeLeft(){let t=this.origRect.left;for(let e of this.scrollCaches)t+=e.origScrollLeft-e.getScrollLeft();return t}computeTop(){let t=this.origRect.top;for(let e of this.scrollCaches)t+=e.origScrollTop-e.getScrollTop();return t}isWithinClipping(t,e){let n={left:t,top:e};for(let t of this.scrollCaches)if(!E(t.getEventTarget())&&!i.pointInsideRect(n,t.clientRect))return!1;return!0}}function E(t){let e=t.tagName;return"HTML"===e||"BODY"===e}class m{constructor(t,e){this.useSubjectCenter=!1,this.requireInitial=!0,this.disablePointCheck=!1,this.initialHit=null,this.movingHit=null,this.finalHit=null,this.handlePointerDown=t=>{let{dragging:e}=this;this.initialHit=null,this.movingHit=null,this.finalHit=null,this.prepareHits(),this.processFirstCoord(t),this.initialHit||!this.requireInitial?(e.setIgnoreMove(!1),this.emitter.trigger("pointerdown",t)):e.setIgnoreMove(!0)},this.handleDragStart=t=>{this.emitter.trigger("dragstart",t),this.handleMove(t,!0)},this.handleDragMove=t=>{this.emitter.trigger("dragmove",t),this.handleMove(t)},this.handlePointerUp=t=>{this.releaseHits(),this.emitter.trigger("pointerup",t)},this.handleDragEnd=t=>{this.movingHit&&this.emitter.trigger("hitupdate",null,!0,t),this.finalHit=this.movingHit,this.movingHit=null,this.emitter.trigger("dragend",t)},this.droppableStore=e,t.emitter.on("pointerdown",this.handlePointerDown),t.emitter.on("dragstart",this.handleDragStart),t.emitter.on("dragmove",this.handleDragMove),t.emitter.on("pointerup",this.handlePointerUp),t.emitter.on("dragend",this.handleDragEnd),this.dragging=t,this.emitter=new i.Emitter}processFirstCoord(t){let e,n={left:t.pageX,top:t.pageY},s=n,r=t.subjectEl;r instanceof HTMLElement&&(e=i.computeRect(r),s=i.constrainPoint(s,e));let o=this.initialHit=this.queryHitForOffset(s.left,s.top);if(o){if(this.useSubjectCenter&&e){let t=i.intersectRects(e,o.rect);t&&(s=i.getRectCenter(t))}this.coordAdjust=i.diffPoints(s,n)}else this.coordAdjust={left:0,top:0}}handleMove(t,e){let i=this.queryHitForOffset(t.pageX+this.coordAdjust.left,t.pageY+this.coordAdjust.top);!e&&S(this.movingHit,i)||(this.movingHit=i,this.emitter.trigger("hitupdate",i,!1,t))}prepareHits(){this.offsetTrackers=i.mapHash(this.droppableStore,t=>(t.component.prepareHits(),new v(t.el)))}releaseHits(){let{offsetTrackers:t}=this;for(let e in t)t[e].destroy();this.offsetTrackers={}}queryHitForOffset(t,e){let{droppableStore:n,offsetTrackers:s}=this,r=null;for(let o in n){let l=n[o].component,a=s[o];if(a&&a.isWithinClipping(t,e)){let n=a.computeLeft(),s=a.computeTop(),h=t-n,c=e-s,{origRect:d}=a,g=d.right-d.left,u=d.bottom-d.top;if(h>=0&&h=0&&cr.layer)&&(t.componentId=o,t.context=l.context,t.rect.left+=n,t.rect.right+=n,t.rect.top+=s,t.rect.bottom+=s,r=t)}}}return r}}function S(t,e){return!t&&!e||Boolean(t)===Boolean(e)&&i.isDateSpansEqual(t.dateSpan,e.dateSpan)}function D(t,e){let i={};for(let n of e.pluginHooks.datePointTransforms)Object.assign(i,n(t,e));var n,s;return Object.assign(i,(n=t,{date:(s=e.dateEnv).toDate(n.range.start),dateStr:s.formatIso(n.range.start,{omitTime:n.allDay}),allDay:n.allDay})),i}class f extends i.Interaction{constructor(t){super(t),this.handlePointerDown=t=>{let{dragging:e}=this,i=t.origEvent.target;e.setIgnoreMove(!this.component.isValidDateDownEl(i))},this.handleDragEnd=t=>{let{component:e}=this,{pointer:i}=this.dragging;if(!i.wasTouchScroll){let{initialHit:i,finalHit:n}=this.hitDragging;if(i&&n&&S(i,n)){let{context:n}=e,s=Object.assign(Object.assign({},D(i.dateSpan,n)),{dayEl:i.dayEl,jsEvent:t.origEvent,view:n.viewApi||n.calendarApi.view});n.emitter.trigger("dateClick",s)}}},this.dragging=new p(t.el),this.dragging.autoScroller.isEnabled=!1;let e=this.hitDragging=new m(this.dragging,i.interactionSettingsToStore(t));e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}}class y extends i.Interaction{constructor(t){super(t),this.dragSelection=null,this.handlePointerDown=t=>{let{component:e,dragging:i}=this,{options:n}=e.context,s=n.selectable&&e.isValidDateDownEl(t.origEvent.target);i.setIgnoreMove(!s),i.delay=t.isTouch?function(t){let{options:e}=t.context,i=e.selectLongPressDelay;null==i&&(i=e.longPressDelay);return i}(e):null},this.handleDragStart=t=>{this.component.context.calendarApi.unselect(t)},this.handleHitUpdate=(t,e)=>{let{context:n}=this.component,s=null,r=!1;if(t){let e=this.hitDragging.initialHit;t.componentId===e.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(e,t)||(s=function(t,e,n){let s=t.dateSpan,r=e.dateSpan,o=[s.range.start,s.range.end,r.range.start,r.range.end];o.sort(i.compareNumbers);let l={};for(let i of n){let n=i(t,e);if(!1===n)return null;n&&Object.assign(l,n)}return l.range={start:o[0],end:o[3]},l.allDay=s.allDay,l}(e,t,n.pluginHooks.dateSelectionTransformers)),s&&i.isDateSelectionValid(s,t.dateProfile,n)||(r=!0,s=null)}s?n.dispatch({type:"SELECT_DATES",selection:s}):e||n.dispatch({type:"UNSELECT_DATES"}),r?i.disableCursor():i.enableCursor(),e||(this.dragSelection=s)},this.handlePointerUp=t=>{this.dragSelection&&(i.triggerDateSelect(this.dragSelection,t,this.component.context),this.dragSelection=null)};let{component:e}=t,{options:n}=e.context,s=this.dragging=new p(t.el);s.touchScrollAllowed=!1,s.minDistance=n.selectMinDistance||0,s.autoScroller.isEnabled=n.dragScroll;let r=this.hitDragging=new m(this.dragging,i.interactionSettingsToStore(t));r.emitter.on("pointerdown",this.handlePointerDown),r.emitter.on("dragstart",this.handleDragStart),r.emitter.on("hitupdate",this.handleHitUpdate),r.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.dragging.destroy()}}class w extends i.Interaction{constructor(t){super(t),this.subjectEl=null,this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=t=>{let e=t.origEvent.target,{component:n,dragging:s}=this,{mirror:r}=s,{options:o}=n.context,l=n.context;this.subjectEl=t.subjectEl;let a=this.subjectSeg=i.getElSeg(t.subjectEl),h=(this.eventRange=a.eventRange).instance.instanceId;this.relevantEvents=i.getRelevantEvents(l.getCurrentData().eventStore,h),s.minDistance=t.isTouch?0:o.eventDragMinDistance,s.delay=t.isTouch&&h!==n.props.eventSelection?function(t){let{options:e}=t.context,i=e.eventLongPressDelay;null==i&&(i=e.longPressDelay);return i}(n):null,o.fixedMirrorParent?r.parentNode=o.fixedMirrorParent:r.parentNode=i.elementClosest(e,".fc"),r.revertDuration=o.dragRevertDuration;let c=n.isValidSegDownEl(e)&&!i.elementClosest(e,".fc-event-resizer");s.setIgnoreMove(!c),this.isDragging=c&&t.subjectEl.classList.contains("fc-event-draggable")},this.handleDragStart=t=>{let e=this.component.context,n=this.eventRange,s=n.instance.instanceId;t.isTouch?s!==this.component.props.eventSelection&&e.dispatch({type:"SELECT_EVENT",eventInstanceId:s}):e.dispatch({type:"UNSELECT_EVENT"}),this.isDragging&&(e.calendarApi.unselect(t),e.emitter.trigger("eventDragStart",{el:this.subjectEl,event:new i.EventImpl(e,n.def,n.instance),jsEvent:t.origEvent,view:e.viewApi}))},this.handleHitUpdate=(t,e)=>{if(!this.isDragging)return;let n=this.relevantEvents,s=this.hitDragging.initialHit,r=this.component.context,o=null,l=null,a=null,h=!1,c={affectedEvents:n,mutatedEvents:i.createEmptyEventStore(),isEvent:!0};if(t){o=t.context;let e=o.options;r===o||e.editable&&e.droppable?(l=function(t,e,n,s){let r=t.dateSpan,o=e.dateSpan,l=r.range.start,a=o.range.start,h={};r.allDay!==o.allDay&&(h.allDay=o.allDay,h.hasEnd=e.context.options.allDayMaintainDuration,l=o.allDay?i.startOfDay(n):n);let c=i.diffDates(l,a,t.context.dateEnv,t.componentId===e.componentId?t.largeUnit:null);c.milliseconds&&(h.allDay=!1);let d={datesDelta:c,standardProps:h};for(let i of s)i(d,t,e);return d}(s,t,this.eventRange.instance.range.start,o.getCurrentData().pluginHooks.eventDragMutationMassagers),l&&(a=i.applyMutationToEventStore(n,o.getCurrentData().eventUiBases,l,o),c.mutatedEvents=a,i.isInteractionValid(c,t.dateProfile,o)||(h=!0,l=null,a=null,c.mutatedEvents=i.createEmptyEventStore()))):o=null}this.displayDrag(o,c),h?i.disableCursor():i.enableCursor(),e||(r===o&&S(s,t)&&(l=null),this.dragging.setMirrorNeedsRevert(!l),this.dragging.setMirrorIsVisible(!t||!this.subjectEl.getRootNode().querySelector(".fc-event-mirror")),this.receivingContext=o,this.validMutation=l,this.mutatedRelevantEvents=a)},this.handlePointerUp=()=>{this.isDragging||this.cleanup()},this.handleDragEnd=t=>{if(this.isDragging){let e=this.component.context,n=e.viewApi,{receivingContext:s,validMutation:r}=this,o=this.eventRange.def,l=this.eventRange.instance,a=new i.EventImpl(e,o,l),h=this.relevantEvents,c=this.mutatedRelevantEvents,{finalHit:d}=this.hitDragging;if(this.clearDrag(),e.emitter.trigger("eventDragStop",{el:this.subjectEl,event:a,jsEvent:t.origEvent,view:n}),r){if(s===e){let s=new i.EventImpl(e,c.defs[o.defId],l?c.instances[l.instanceId]:null);e.dispatch({type:"MERGE_EVENTS",eventStore:c});let d={oldEvent:a,event:s,relatedEvents:i.buildEventApis(c,e,l),revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:h})}},g={};for(let t of e.getCurrentData().pluginHooks.eventDropTransformers)Object.assign(g,t(r,e));e.emitter.trigger("eventDrop",Object.assign(Object.assign(Object.assign({},d),g),{el:t.subjectEl,delta:r.datesDelta,jsEvent:t.origEvent,view:n})),e.emitter.trigger("eventChange",d)}else if(s){let r={event:a,relatedEvents:i.buildEventApis(h,e,l),revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:h})}};e.emitter.trigger("eventLeave",Object.assign(Object.assign({},r),{draggedEl:t.subjectEl,view:n})),e.dispatch({type:"REMOVE_EVENTS",eventStore:h}),e.emitter.trigger("eventRemove",r);let g=c.defs[o.defId],u=c.instances[l.instanceId],p=new i.EventImpl(s,g,u);s.dispatch({type:"MERGE_EVENTS",eventStore:c});let v={event:p,relatedEvents:i.buildEventApis(c,s,u),revert(){s.dispatch({type:"REMOVE_EVENTS",eventStore:c})}};s.emitter.trigger("eventAdd",v),t.isTouch&&s.dispatch({type:"SELECT_EVENT",eventInstanceId:l.instanceId}),s.emitter.trigger("drop",Object.assign(Object.assign({},D(d.dateSpan,s)),{draggedEl:t.subjectEl,jsEvent:t.origEvent,view:d.context.viewApi})),s.emitter.trigger("eventReceive",Object.assign(Object.assign({},v),{draggedEl:t.subjectEl,view:d.context.viewApi}))}}else e.emitter.trigger("_noEventDrop")}this.cleanup()};let{component:e}=this,{options:n}=e.context,s=this.dragging=new p(t.el);s.pointer.selector=w.SELECTOR,s.touchScrollAllowed=!1,s.autoScroller.isEnabled=n.dragScroll;let r=this.hitDragging=new m(this.dragging,i.interactionSettingsStore);r.useSubjectCenter=t.useEventCenter,r.emitter.on("pointerdown",this.handlePointerDown),r.emitter.on("dragstart",this.handleDragStart),r.emitter.on("hitupdate",this.handleHitUpdate),r.emitter.on("pointerup",this.handlePointerUp),r.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}displayDrag(t,e){let n=this.component.context,s=this.receivingContext;s&&s!==t&&(s===n?s.dispatch({type:"SET_EVENT_DRAG",state:{affectedEvents:e.affectedEvents,mutatedEvents:i.createEmptyEventStore(),isEvent:!0}}):s.dispatch({type:"UNSET_EVENT_DRAG"})),t&&t.dispatch({type:"SET_EVENT_DRAG",state:e})}clearDrag(){let t=this.component.context,{receivingContext:e}=this;e&&e.dispatch({type:"UNSET_EVENT_DRAG"}),t!==e&&t.dispatch({type:"UNSET_EVENT_DRAG"})}cleanup(){this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null}}w.SELECTOR=".fc-event-draggable, .fc-event-resizable";class T extends i.Interaction{constructor(t){super(t),this.draggingSegEl=null,this.draggingSeg=null,this.eventRange=null,this.relevantEvents=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=t=>{let{component:e}=this,n=this.querySegEl(t),s=i.getElSeg(n),r=this.eventRange=s.eventRange;this.dragging.minDistance=e.context.options.eventDragMinDistance,this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(t.origEvent.target)||t.isTouch&&this.component.props.eventSelection!==r.instance.instanceId)},this.handleDragStart=t=>{let{context:e}=this.component,n=this.eventRange;this.relevantEvents=i.getRelevantEvents(e.getCurrentData().eventStore,this.eventRange.instance.instanceId);let s=this.querySegEl(t);this.draggingSegEl=s,this.draggingSeg=i.getElSeg(s),e.calendarApi.unselect(),e.emitter.trigger("eventResizeStart",{el:s,event:new i.EventImpl(e,n.def,n.instance),jsEvent:t.origEvent,view:e.viewApi})},this.handleHitUpdate=(t,e,n)=>{let{context:s}=this.component,r=this.relevantEvents,o=this.hitDragging.initialHit,l=this.eventRange.instance,a=null,h=null,c=!1,d={affectedEvents:r,mutatedEvents:i.createEmptyEventStore(),isEvent:!0};if(t){t.componentId===o.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(o,t)||(a=function(t,e,n,s){let r=t.context.dateEnv,o=t.dateSpan.range.start,l=e.dateSpan.range.start,a=i.diffDates(o,l,r,t.largeUnit);if(n){if(r.add(s.start,a)s.start)return{endDelta:a};return null}(o,t,n.subjectEl.classList.contains("fc-event-resizer-start"),l.range))}a&&(h=i.applyMutationToEventStore(r,s.getCurrentData().eventUiBases,a,s),d.mutatedEvents=h,i.isInteractionValid(d,t.dateProfile,s)||(c=!0,a=null,h=null,d.mutatedEvents=null)),h?s.dispatch({type:"SET_EVENT_RESIZE",state:d}):s.dispatch({type:"UNSET_EVENT_RESIZE"}),c?i.disableCursor():i.enableCursor(),e||(a&&S(o,t)&&(a=null),this.validMutation=a,this.mutatedRelevantEvents=h)},this.handleDragEnd=t=>{let{context:e}=this.component,n=this.eventRange.def,s=this.eventRange.instance,r=new i.EventImpl(e,n,s),o=this.relevantEvents,l=this.mutatedRelevantEvents;if(e.emitter.trigger("eventResizeStop",{el:this.draggingSegEl,event:r,jsEvent:t.origEvent,view:e.viewApi}),this.validMutation){let a=new i.EventImpl(e,l.defs[n.defId],s?l.instances[s.instanceId]:null);e.dispatch({type:"MERGE_EVENTS",eventStore:l});let h={oldEvent:r,event:a,relatedEvents:i.buildEventApis(l,e,s),revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:o})}};e.emitter.trigger("eventResize",Object.assign(Object.assign({},h),{el:this.draggingSegEl,startDelta:this.validMutation.startDelta||i.createDuration(0),endDelta:this.validMutation.endDelta||i.createDuration(0),jsEvent:t.origEvent,view:e.viewApi})),e.emitter.trigger("eventChange",h)}else e.emitter.trigger("_noEventResize");this.draggingSeg=null,this.relevantEvents=null,this.validMutation=null};let{component:e}=t,n=this.dragging=new p(t.el);n.pointer.selector=".fc-event-resizer",n.touchScrollAllowed=!1,n.autoScroller.isEnabled=e.context.options.dragScroll;let s=this.hitDragging=new m(this.dragging,i.interactionSettingsToStore(t));s.emitter.on("pointerdown",this.handlePointerDown),s.emitter.on("dragstart",this.handleDragStart),s.emitter.on("hitupdate",this.handleHitUpdate),s.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}querySegEl(t){return i.elementClosest(t.subjectEl,".fc-event")}}const b={fixedMirrorParent:i.identity},M={dateClick:i.identity,eventDragStart:i.identity,eventDragStop:i.identity,eventDrop:i.identity,eventResizeStart:i.identity,eventResizeStop:i.identity,eventResize:i.identity,drop:i.identity,eventReceive:i.identity,eventLeave:i.identity};class C{constructor(t,e){this.receivingContext=null,this.droppableEvent=null,this.suppliedDragMeta=null,this.dragMeta=null,this.handleDragStart=t=>{this.dragMeta=this.buildDragMeta(t.subjectEl)},this.handleHitUpdate=(t,e,n)=>{let{dragging:s}=this.hitDragging,r=null,o=null,l=!1,a={affectedEvents:i.createEmptyEventStore(),mutatedEvents:i.createEmptyEventStore(),isEvent:this.dragMeta.create};t&&(r=t.context,this.canDropElOnCalendar(n.subjectEl,r)&&(o=function(t,e,n){let s=Object.assign({},e.leftoverProps);for(let i of n.pluginHooks.externalDefTransforms)Object.assign(s,i(t,e));let{refined:r,extra:o}=i.refineEventDef(s,n),l=i.parseEventDef(r,o,e.sourceId,t.allDay,n.options.forceEventDuration||Boolean(e.duration),n),a=t.range.start;t.allDay&&e.startTime&&(a=n.dateEnv.add(a,e.startTime));let h=e.duration?n.dateEnv.add(a,e.duration):i.getDefaultEventEnd(t.allDay,a,n),c=i.createEventInstance(l.defId,{start:a,end:h});return{def:l,instance:c}}(t.dateSpan,this.dragMeta,r),a.mutatedEvents=i.eventTupleToStore(o),l=!i.isInteractionValid(a,t.dateProfile,r),l&&(a.mutatedEvents=i.createEmptyEventStore(),o=null))),this.displayDrag(r,a),s.setMirrorIsVisible(e||!o||!document.querySelector(".fc-event-mirror")),l?i.disableCursor():i.enableCursor(),e||(s.setMirrorNeedsRevert(!o),this.receivingContext=r,this.droppableEvent=o)},this.handleDragEnd=t=>{let{receivingContext:e,droppableEvent:n}=this;if(this.clearDrag(),e&&n){let s=this.hitDragging.finalHit,r=s.context.viewApi,o=this.dragMeta;if(e.emitter.trigger("drop",Object.assign(Object.assign({},D(s.dateSpan,e)),{draggedEl:t.subjectEl,jsEvent:t.origEvent,view:r})),o.create){let s=i.eventTupleToStore(n);e.dispatch({type:"MERGE_EVENTS",eventStore:s}),t.isTouch&&e.dispatch({type:"SELECT_EVENT",eventInstanceId:n.instance.instanceId}),e.emitter.trigger("eventReceive",{event:new i.EventImpl(e,n.def,n.instance),relatedEvents:[],revert(){e.dispatch({type:"REMOVE_EVENTS",eventStore:s})},draggedEl:t.subjectEl,view:r})}}this.receivingContext=null,this.droppableEvent=null};let n=this.hitDragging=new m(t,i.interactionSettingsStore);n.requireInitial=!1,n.emitter.on("dragstart",this.handleDragStart),n.emitter.on("hitupdate",this.handleHitUpdate),n.emitter.on("dragend",this.handleDragEnd),this.suppliedDragMeta=e}buildDragMeta(t){return"object"==typeof this.suppliedDragMeta?i.parseDragMeta(this.suppliedDragMeta):"function"==typeof this.suppliedDragMeta?i.parseDragMeta(this.suppliedDragMeta(t)):function(t){let e=function(t,e){let n=i.config.dataAttrPrefix,s=(n?n+"-":"")+e;return t.getAttribute("data-"+s)||""}(t,"event"),n=e?JSON.parse(e):{create:!1};return i.parseDragMeta(n)}(t)}displayDrag(t,e){let i=this.receivingContext;i&&i!==t&&i.dispatch({type:"UNSET_EVENT_DRAG"}),t&&t.dispatch({type:"SET_EVENT_DRAG",state:e})}clearDrag(){this.receivingContext&&this.receivingContext.dispatch({type:"UNSET_EVENT_DRAG"})}canDropElOnCalendar(t,e){let n=e.options.dropAccept;return"function"==typeof n?n.call(e.calendarApi,t):"string"!=typeof n||!n||Boolean(i.elementMatches(t,n))}}i.config.dataAttrPrefix="";class R extends i.ElementDragging{constructor(t){super(t),this.shouldIgnoreMove=!1,this.mirrorSelector="",this.currentMirrorEl=null,this.handlePointerDown=t=>{this.emitter.trigger("pointerdown",t),this.shouldIgnoreMove||this.emitter.trigger("dragstart",t)},this.handlePointerMove=t=>{this.shouldIgnoreMove||this.emitter.trigger("dragmove",t)},this.handlePointerUp=t=>{this.emitter.trigger("pointerup",t),this.shouldIgnoreMove||this.emitter.trigger("dragend",t)};let e=this.pointer=new o(t);e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("pointermove",this.handlePointerMove),e.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.pointer.destroy()}setIgnoreMove(t){this.shouldIgnoreMove=t}setMirrorIsVisible(t){if(t)this.currentMirrorEl&&(this.currentMirrorEl.style.visibility="",this.currentMirrorEl=null);else{let t=this.mirrorSelector?document.querySelector(this.mirrorSelector):null;t&&(this.currentMirrorEl=t,t.style.visibility="hidden")}}}var I=e.createPlugin({name:"@fullcalendar/interaction",componentInteractions:[f,y,w,T],calendarInteractions:[class{constructor(t){this.context=t,this.isRecentPointerDateSelect=!1,this.matchesCancel=!1,this.matchesEvent=!1,this.onSelect=t=>{t.jsEvent&&(this.isRecentPointerDateSelect=!0)},this.onDocumentPointerDown=t=>{let e=this.context.options.unselectCancel,n=i.getEventTargetViaRoot(t.origEvent);this.matchesCancel=!!i.elementClosest(n,e),this.matchesEvent=!!i.elementClosest(n,w.SELECTOR)},this.onDocumentPointerUp=t=>{let{context:e}=this,{documentPointer:i}=this,n=e.getCurrentData();if(!i.wasTouchScroll){if(n.dateSelection&&!this.isRecentPointerDateSelect){let i=e.options.unselectAuto;!i||i&&this.matchesCancel||e.calendarApi.unselect(t)}n.eventSelection&&!this.matchesEvent&&e.dispatch({type:"UNSELECT_EVENT"})}this.isRecentPointerDateSelect=!1};let e=this.documentPointer=new o(document);e.shouldIgnoreMove=!0,e.shouldWatchScroll=!1,e.emitter.on("pointerdown",this.onDocumentPointerDown),e.emitter.on("pointerup",this.onDocumentPointerUp),t.emitter.on("select",this.onSelect)}destroy(){this.context.emitter.off("select",this.onSelect),this.documentPointer.destroy()}}],elementDraggingImpl:p,optionRefiners:b,listenerRefiners:M});return e.globalPlugins.push(I),t.Draggable=class{constructor(t,e={}){this.handlePointerDown=t=>{let{dragging:e}=this,{minDistance:n,longPressDelay:s}=this.settings;e.minDistance=null!=n?n:t.isTouch?0:i.BASE_OPTION_DEFAULTS.eventDragMinDistance,e.delay=t.isTouch?null!=s?s:i.BASE_OPTION_DEFAULTS.longPressDelay:0},this.handleDragStart=t=>{t.isTouch&&this.dragging.delay&&t.subjectEl.classList.contains("fc-event")&&this.dragging.mirror.getMirrorEl().classList.add("fc-event-selected")},this.settings=e;let n=this.dragging=new p(t);n.touchScrollAllowed=!1,null!=e.itemSelector&&(n.pointer.selector=e.itemSelector),null!=e.appendTo&&(n.mirror.parentNode=e.appendTo),n.emitter.on("pointerdown",this.handlePointerDown),n.emitter.on("dragstart",this.handleDragStart),new C(n,e.eventData)}destroy(){this.dragging.destroy()}},t.ThirdPartyDraggable=class{constructor(t,e){let i=document;t===document||t instanceof Element?(i=t,e=e||{}):e=t||{};let n=this.dragging=new R(i);"string"==typeof e.itemSelector?n.pointer.selector=e.itemSelector:i===document&&(n.pointer.selector="[data-event]"),"string"==typeof e.mirrorSelector&&(n.mirrorSelector=e.mirrorSelector),new C(n,e.eventData).hitDragging.disablePointCheck=!0}destroy(){this.dragging.destroy()}},t.default=I,Object.defineProperty(t,"__esModule",{value:!0}),t}({},FullCalendar,FullCalendar.Internal); \ No newline at end of file -- cgit v1.2.3