UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

280 lines (279 loc) • 11.9 kB
/** * DevExtreme (esm/__internal/scheduler/appointment_drag_controller.js) * Version: 26.1.4 * Build date: Fri Jul 24 2026 * * Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import eventsEngine from "../../common/core/events/core/events_engine"; import { enter as dragEventEnter, leave as dragEventLeave } from "../../common/core/events/drag"; import { addNamespace } from "../../common/core/events/utils/index"; import $ from "../../core/renderer"; import { extend } from "../../core/utils/extend"; import { getWindow } from "../../core/utils/window"; import { getHeight, getWidth } from "../core/utils/m_size"; import Draggable from "../m_draggable"; import { APPOINTMENT_CLASSES } from "./appointments_new/const"; const APPOINTMENT_DRAG_SOURCE_CLASS = "dx-scheduler-appointment-drag-source"; const TOOLTIP_LIST_ITEM_CLASS = "dx-list-item"; const HIGHLIGHTED_CELL_CLASS = "dx-scheduler-date-table-droppable-cell"; const CELL_SELECTOR = ".dx-scheduler-date-table-cell, .dx-scheduler-all-day-table-cell"; const DRAG_ENTER_EVENT = addNamespace(dragEventEnter, "dxSchedulerAppointmentDrag"); const DRAG_LEAVE_EVENT = addNamespace(dragEventLeave, "dxSchedulerAppointmentDrag"); export class AppointmentDragController { constructor(options) { this.options = options; this.workSpaceDraggable = null; this.tooltipDraggable = null; this.$initialCell = null; this.$highlightedCell = null; this.$dragClone = null; this.$workSpace = null; this.draggedItemData = null; this.onExternalDragEnter = e => { if (this.draggedItemData) { return } this.highlightCell($(e.target).closest(CELL_SELECTOR)) }; this.onExternalDragLeave = () => { if (this.draggedItemData) { return } this.removeCellHighlight() } } createWorkSpaceDraggable($workSpace, draggableOptions) { const config = Object.assign({}, this.getCommonDraggableConfig(), { filter: `.${APPOINTMENT_CLASSES.CONTAINER}`, dragTemplate: dragInfo => { this.$dragClone = $(dragInfo.itemElement).clone(); this.$dragClone.css({ top: "", left: "" }); this.$dragClone.removeClass(APPOINTMENT_DRAG_SOURCE_CLASS); return this.$dragClone }, onDragStart: e => { this.onDragStart(e, draggableOptions.getAppointmentData($(e.itemElement))) } }); this.workSpaceDraggable = this.options.createComponent($workSpace, Draggable, config); this.$workSpace = $workSpace; eventsEngine.on($workSpace, DRAG_ENTER_EVENT, CELL_SELECTOR, this.onExternalDragEnter); eventsEngine.on($workSpace, DRAG_LEAVE_EVENT, this.onExternalDragLeave) } disposeWorkSpaceDraggable() { var _this$workSpaceDragga; if (this.$workSpace) { eventsEngine.off(this.$workSpace, DRAG_ENTER_EVENT); eventsEngine.off(this.$workSpace, DRAG_LEAVE_EVENT); this.$workSpace = null } null === (_this$workSpaceDragga = this.workSpaceDraggable) || void 0 === _this$workSpaceDragga || _this$workSpaceDragga.dispose(); this.workSpaceDraggable = null } createTooltipDraggable($tooltipList, draggableOptions) { let tooltipItem = null; const config = Object.assign({}, this.getCommonDraggableConfig(), { filter: ".dx-list-item", dragTemplate: () => { if (!tooltipItem) { return $() } const appointmentViewModel = tooltipItem.settings; this.$dragClone = draggableOptions.dragTemplate(appointmentViewModel); this.$dragClone.css({ top: "", left: "" }); this.$dragClone.removeClass(APPOINTMENT_DRAG_SOURCE_CLASS); return this.$dragClone }, onDragStart: e => { tooltipItem = $(e.itemElement).data("dxListItemData"); this.onDragStart(e, { appointmentData: tooltipItem.appointment, targetedAppointmentData: tooltipItem.targetedAppointment ?? tooltipItem.appointment }) }, cursorOffset: () => ({ x: getWidth(this.$dragClone) / 2, y: getHeight(this.$dragClone) / 2 }) }); this.tooltipDraggable = this.options.createComponent($tooltipList, Draggable, config) } disposeTooltipDraggable() { var _this$tooltipDraggabl; null === (_this$tooltipDraggabl = this.tooltipDraggable) || void 0 === _this$tooltipDraggabl || _this$tooltipDraggabl.dispose(); this.tooltipDraggable = null } getCommonDraggableConfig() { const config = this.options.getAppointmentDraggingConfig(); const draggableConfig = { component: this.options.component, container: this.options.$draggableContainer().get(0), onCancelByEsc: true, onDragMove: this.onDragMove.bind(this), onDragEnd: this.onDragEnd.bind(this), onDragCancel: this.onDragCancel.bind(this), onDrop: this.onDrop.bind(this) }; return extend(draggableConfig, { autoScroll: config.autoScroll, data: config.data, group: config.group, scrollSpeed: config.scrollSpeed, scrollSensitivity: config.scrollSensitivity }) } onDragStart(e, draggedItemData) { var _this$options$getAppo, _this$options$getAppo2; e.itemData = draggedItemData.appointmentData; if (!this.options.canDragAppointment(draggedItemData.appointmentData)) { e.cancel = true; return } null === (_this$options$getAppo = (_this$options$getAppo2 = this.options.getAppointmentDraggingConfig()).onDragStart) || void 0 === _this$options$getAppo || _this$options$getAppo.call(_this$options$getAppo2, e); if (e.cancel) { return } this.draggedItemData = draggedItemData; this.$initialCell = this.options.getCellFromDragTarget($(e.itemElement)); this.options.hideAppointmentTooltip(); $(e.itemElement).addClass(APPOINTMENT_DRAG_SOURCE_CLASS) } onDragMove(e) { var _this$options$getAppo3, _this$options$getAppo4; null === (_this$options$getAppo3 = (_this$options$getAppo4 = this.options.getAppointmentDraggingConfig()).onDragMove) || void 0 === _this$options$getAppo3 || _this$options$getAppo3.call(_this$options$getAppo4, e); if (e.cancel) { return } const $cell = this.options.getCellFromDragTarget($(this.$dragClone)); if (!$cell) { this.removeHighlightedCell(); return } this.highlightCell($cell) } onDragEnd(e) { var _this$$initialCell$ge, _this$options$getAppo5, _this$options$getAppo6, _this$$initialCell; const { draggedItemData: draggedItemData } = this; this.draggedItemData = null; if (!draggedItemData) { this.removeDraggingClasses($(e.itemElement)); return } if (this.$initialCell && !(null !== (_this$$initialCell$ge = this.$initialCell.get(0)) && void 0 !== _this$$initialCell$ge && _this$$initialCell$ge.isConnected)) { this.$initialCell = null } const isSameComponent = e.fromComponent === e.toComponent; const $dropCell = this.getSourceDropCell(e); e.toItemData = Object.assign({}, e.itemData, this.options.getUpdatedItemData(e.itemData, $dropCell ?? this.$initialCell ?? void 0)); null === (_this$options$getAppo5 = (_this$options$getAppo6 = this.options.getAppointmentDraggingConfig()).onDragEnd) || void 0 === _this$options$getAppo5 || _this$options$getAppo5.call(_this$options$getAppo6, e); if (true === e.cancel) { this.removeDraggingClasses($(e.itemElement)); return } if (!isSameComponent) { var _this$options$getAppo7, _this$options$getAppo8; null === (_this$options$getAppo7 = (_this$options$getAppo8 = this.options.getAppointmentDraggingConfig()).onRemove) || void 0 === _this$options$getAppo7 || _this$options$getAppo7.call(_this$options$getAppo8, e); this.removeDraggingClasses($(e.itemElement)); return } const isSameCell = (null === (_this$$initialCell = this.$initialCell) || void 0 === _this$$initialCell ? void 0 : _this$$initialCell.is($dropCell ?? $())) ?? false; if (!$dropCell || isSameCell) { this.removeDraggingClasses($(e.itemElement)); return } this.options.updateAppointmentOnDrop(draggedItemData.appointmentData, draggedItemData.targetedAppointmentData, $dropCell).finally(() => { this.removeDraggingClasses($(e.itemElement)) }).catch(err => { throw err }); this.removeCellHighlight() } getSourceDropCell(e) { const $cell = this.$highlightedCell; if (!$cell || 0 === $cell.closest(e.fromComponent.$element()).length) { return null } return $cell } onDrop(e) { var _this$options$getAppo9, _this$options$getAppo0; if (e.fromComponent === e.toComponent) { return } const $cell = this.getDropCell(e) ?? void 0; e.itemData = Object.assign({}, e.itemData, this.options.getUpdatedItemData(e.itemData, $cell)); null === (_this$options$getAppo9 = (_this$options$getAppo0 = this.options.getAppointmentDraggingConfig()).onAdd) || void 0 === _this$options$getAppo9 || _this$options$getAppo9.call(_this$options$getAppo0, e); this.removeCellHighlight() } getDropCell(e) { const point = this.getDropPoint(e); const $cellFromPoint = point ? this.options.getCellFromPoint(point.x, point.y) : null; if ($cellFromPoint) { return $cellFromPoint } const $droppableCell = this.options.getDroppableCell(); return $droppableCell.length ? $droppableCell : null } getDropPoint(e) { const { event: event } = e; if (!event) { return null } const window = getWindow(); const toClient = (client, page, scroll) => client ?? (null != page ? page - (scroll || 0) : void 0); const x = toClient(event.clientX, event.pageX, window.scrollX); const y = toClient(event.clientY, event.pageY, window.scrollY); return null != x && null != y ? { x: x, y: y } : null } onDragCancel(e) { this.draggedItemData = null; this.removeDraggingClasses($(e.itemElement)) } removeDraggingClasses($dragSource) { $dragSource.removeClass(APPOINTMENT_DRAG_SOURCE_CLASS); this.removeCellHighlight() } highlightCell($cell) { this.removeHighlightedCell(); $cell.addClass(HIGHLIGHTED_CELL_CLASS); this.$highlightedCell = $cell } removeHighlightedCell() { var _this$$highlightedCel; null === (_this$$highlightedCel = this.$highlightedCell) || void 0 === _this$$highlightedCel || _this$$highlightedCel.removeClass(HIGHLIGHTED_CELL_CLASS); this.$highlightedCell = null } removeCellHighlight() { this.removeHighlightedCell(); this.options.getDroppableCell().removeClass(HIGHLIGHTED_CELL_CLASS) } }