devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
917 lines (914 loc) • 38.5 kB
JavaScript
/**
* DevExtreme (cjs/__internal/m_draggable.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _position = _interopRequireDefault(require("../common/core/animation/position"));
var _translator = require("../common/core/animation/translator");
var _events_engine = _interopRequireDefault(require("../common/core/events/core/events_engine"));
var _drag = require("../common/core/events/drag");
var _pointer = _interopRequireDefault(require("../common/core/events/pointer"));
var _index = require("../common/core/events/utils/index");
var _component_registrator = _interopRequireDefault(require("../core/component_registrator"));
var _dom_adapter = _interopRequireDefault(require("../core/dom_adapter"));
var _element = require("../core/element");
var _renderer = _interopRequireDefault(require("../core/renderer"));
var _empty_template = require("../core/templates/empty_template");
var _common = require("../core/utils/common");
var _deferred = require("../core/utils/deferred");
var _extend = require("../core/utils/extend");
var _inflector = require("../core/utils/inflector");
var _position2 = require("../core/utils/position");
var _size = require("../core/utils/size");
var _string = require("../core/utils/string");
var _type = require("../core/utils/type");
var _view_port = require("../core/utils/view_port");
var _window = require("../core/utils/window");
var _dom_component = _interopRequireDefault(require("./core/widget/dom_component"));
var _m_animator = _interopRequireDefault(require("./ui/scroll_view/m_animator"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
function _extends() {
return _extends = Object.assign ? Object.assign.bind() : function(n) {
for (var e = 1; e < arguments.length; e++) {
var t = arguments[e];
for (var r in t) {
({}).hasOwnProperty.call(t, r) && (n[r] = t[r])
}
}
return n
}, _extends.apply(null, arguments)
}
const window = (0, _window.getWindow)();
const KEYDOWN_EVENT = "keydown";
const DRAGGABLE = "dxDraggable";
const DRAGSTART_EVENT_NAME = (0, _index.addNamespace)(_drag.start, DRAGGABLE);
const DRAG_EVENT_NAME = (0, _index.addNamespace)(_drag.move, DRAGGABLE);
const DRAGEND_EVENT_NAME = (0, _index.addNamespace)(_drag.end, DRAGGABLE);
const DRAG_ENTER_EVENT_NAME = (0, _index.addNamespace)(_drag.enter, DRAGGABLE);
const DRAGEND_LEAVE_EVENT_NAME = (0, _index.addNamespace)(_drag.leave, DRAGGABLE);
const POINTERDOWN_EVENT_NAME = (0, _index.addNamespace)(_pointer.default.down, DRAGGABLE);
const KEYDOWN_EVENT_NAME = (0, _index.addNamespace)("keydown", DRAGGABLE);
const CLONE_CLASS = "clone";
let targetDraggable;
let sourceDraggable;
const ANONYMOUS_TEMPLATE_NAME = "content";
const getMousePosition = event => ({
x: event.pageX - (0, _renderer.default)(window).scrollLeft(),
y: event.pageY - (0, _renderer.default)(window).scrollTop()
});
const GESTURE_COVER_CLASS = "dx-gesture-cover";
const OVERLAY_WRAPPER_CLASS = "dx-overlay-wrapper";
const OVERLAY_CONTENT_CLASS = "dx-overlay-content";
class ScrollHelper {
constructor(orientation, component) {
this._$scrollableAtPointer = null;
this._preventScroll = true;
this._component = component;
if ("vertical" === orientation) {
this._scrollValue = "scrollTop";
this._overFlowAttr = "overflowY";
this._sizeAttr = "height";
this._scrollSizeProp = "scrollHeight";
this._clientSizeProp = "clientHeight";
this._limitProps = {
start: "top",
end: "bottom"
}
} else {
this._scrollValue = "scrollLeft";
this._overFlowAttr = "overflowX";
this._sizeAttr = "width";
this._scrollSizeProp = "scrollWidth";
this._clientSizeProp = "clientWidth";
this._limitProps = {
start: "left",
end: "right"
}
}
}
updateScrollable(elements, mousePosition) {
let isScrollableFound = false;
elements.some((element => {
const $element = (0, _renderer.default)(element);
const isTargetOverOverlayWrapper = $element.hasClass("dx-overlay-wrapper");
const isTargetOverOverlayContent = $element.hasClass("dx-overlay-content");
if (isTargetOverOverlayWrapper || isTargetOverOverlayContent) {
return true
}
isScrollableFound = this._trySetScrollable(element, mousePosition);
return isScrollableFound
}));
if (!isScrollableFound) {
this._$scrollableAtPointer = null;
this._scrollSpeed = 0
}
}
isScrolling() {
return !!this._scrollSpeed
}
isScrollable($element) {
return ("auto" === $element.css(this._overFlowAttr) || $element.hasClass("dx-scrollable-container")) && $element.prop(this._scrollSizeProp) > Math.ceil("width" === this._sizeAttr ? (0, _size.getWidth)($element) : (0, _size.getHeight)($element))
}
_trySetScrollable(element, mousePosition) {
const that = this;
const $element = (0, _renderer.default)(element);
let distanceToBorders;
const sensitivity = that._component.option("scrollSensitivity");
let isScrollable = that.isScrollable($element);
if (isScrollable) {
distanceToBorders = that._calculateDistanceToBorders($element, mousePosition);
if (sensitivity > distanceToBorders[that._limitProps.start]) {
if (!that._preventScroll) {
that._scrollSpeed = -that._calculateScrollSpeed(distanceToBorders[that._limitProps.start]);
that._$scrollableAtPointer = $element
}
} else if (sensitivity > distanceToBorders[that._limitProps.end]) {
if (!that._preventScroll) {
that._scrollSpeed = that._calculateScrollSpeed(distanceToBorders[that._limitProps.end]);
that._$scrollableAtPointer = $element
}
} else {
isScrollable = false;
that._preventScroll = false
}
}
return isScrollable
}
_calculateDistanceToBorders($area, mousePosition) {
const area = $area.get(0);
let areaBoundingRect;
if (area) {
areaBoundingRect = (0, _position2.getBoundingRect)(area);
return {
left: mousePosition.x - areaBoundingRect.left,
top: mousePosition.y - areaBoundingRect.top,
right: areaBoundingRect.right - mousePosition.x,
bottom: areaBoundingRect.bottom - mousePosition.y
}
}
return {}
}
_calculateScrollSpeed(distance) {
const component = this._component;
const sensitivity = component.option("scrollSensitivity");
const maxSpeed = component.option("scrollSpeed");
return Math.ceil(((sensitivity - distance) / sensitivity) ** 2 * maxSpeed)
}
scrollByStep() {
const that = this;
if (that._$scrollableAtPointer && that._scrollSpeed) {
if (that._$scrollableAtPointer.hasClass("dx-scrollable-container")) {
const $scrollable = that._$scrollableAtPointer.closest(".dx-scrollable");
const scrollableInstance = $scrollable.data("dxScrollable") || $scrollable.data("dxScrollView");
if (scrollableInstance) {
const nextScrollPosition = scrollableInstance.scrollOffset()[that._limitProps.start] + that._scrollSpeed;
scrollableInstance.scrollTo({
[that._limitProps.start]: nextScrollPosition
})
}
} else {
const nextScrollPosition = that._$scrollableAtPointer[that._scrollValue]() + that._scrollSpeed;
that._$scrollableAtPointer[that._scrollValue](nextScrollPosition)
}
const dragMoveArgs = that._component._dragMoveArgs;
if (dragMoveArgs) {
that._component._dragMoveHandler(dragMoveArgs)
}
}
}
reset() {
this._$scrollableAtPointer = null;
this._scrollSpeed = 0;
this._preventScroll = true
}
isOutsideScrollable($scrollable, event) {
if (!$scrollable) {
return false
}
const scrollableSize = (0, _position2.getBoundingRect)($scrollable.get(0));
const start = scrollableSize[this._limitProps.start];
const size = scrollableSize[this._sizeAttr];
const mousePosition = getMousePosition(event);
const location = "width" === this._sizeAttr ? mousePosition.x : mousePosition.y;
return location < start || location > start + size
}
}
class ScrollAnimator extends _m_animator.default {
ctor(strategy) {
super.ctor();
this._strategy = strategy
}
_step() {
const horizontalScrollHelper = this._strategy._horizontalScrollHelper;
const verticalScrollHelper = this._strategy._verticalScrollHelper;
null === horizontalScrollHelper || void 0 === horizontalScrollHelper || horizontalScrollHelper.scrollByStep();
null === verticalScrollHelper || void 0 === verticalScrollHelper || verticalScrollHelper.scrollByStep()
}
}
class Draggable extends _dom_component.default {
reset() {}
dragMove(e) {}
dragEnter() {}
dragLeave() {}
dragEnd(sourceEvent) {
const sourceDraggable = this._getSourceDraggable();
sourceDraggable._fireRemoveEvent(sourceEvent);
return (0, _deferred.Deferred)().resolve()
}
_fireRemoveEvent(sourceEvent) {}
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
onDragStart: null,
onDragMove: null,
onDragEnd: null,
onDragEnter: null,
onDragLeave: null,
onDragCancel: null,
onCancelByEsc: false,
onDrop: null,
immediate: true,
dragDirection: "both",
boundOffset: 0,
allowMoveByClick: false,
itemData: null,
contentTemplate: "content",
handle: "",
filter: "",
clone: false,
autoScroll: true,
scrollSpeed: 30,
scrollSensitivity: 60
})
}
_setOptionsByReference() {
super._setOptionsByReference.apply(this, arguments);
(0, _extend.extend)(this._optionsByReference, {
component: true,
group: true,
itemData: true,
data: true
})
}
_init() {
super._init();
this._attachEventHandlers();
this._scrollAnimator = new ScrollAnimator(this);
this._horizontalScrollHelper = new ScrollHelper("horizontal", this);
this._verticalScrollHelper = new ScrollHelper("vertical", this);
this._initScrollTop = 0;
this._initScrollLeft = 0
}
_normalizeCursorOffset(offset) {
if ((0, _type.isObject)(offset)) {
offset = {
h: offset.x,
v: offset.y
}
}
offset = (0, _common.splitPair)(offset).map((value => parseFloat(value)));
return {
left: offset[0],
top: 1 === offset.length ? offset[0] : offset[1]
}
}
_getNormalizedCursorOffset(offset, options) {
if ((0, _type.isFunction)(offset)) {
offset = offset.call(this, options)
}
return this._normalizeCursorOffset(offset)
}
_calculateElementOffset(options) {
let elementOffset;
let dragElementOffset;
const {
event: event
} = options;
const $element = (0, _renderer.default)(options.itemElement);
const $dragElement = (0, _renderer.default)(options.dragElement);
const isCloned = this._dragElementIsCloned();
const cursorOffset = this.option("cursorOffset");
let normalizedCursorOffset = {
left: 0,
top: 0
};
const currentLocate = this._initialLocate = (0, _translator.locate)($dragElement);
if (isCloned || options.initialOffset || cursorOffset) {
elementOffset = options.initialOffset || $element.offset();
if (cursorOffset) {
normalizedCursorOffset = this._getNormalizedCursorOffset(cursorOffset, options);
if (isFinite(normalizedCursorOffset.left)) {
elementOffset.left = event.pageX
}
if (isFinite(normalizedCursorOffset.top)) {
elementOffset.top = event.pageY
}
}
dragElementOffset = $dragElement.offset();
elementOffset.top -= dragElementOffset.top + (normalizedCursorOffset.top || 0) - currentLocate.top;
elementOffset.left -= dragElementOffset.left + (normalizedCursorOffset.left || 0) - currentLocate.left
}
return elementOffset
}
_initPosition(options) {
const $dragElement = (0, _renderer.default)(options.dragElement);
const elementOffset = this._calculateElementOffset(options);
if (elementOffset) {
this._move(elementOffset, $dragElement)
}
this._startPosition = (0, _translator.locate)($dragElement)
}
_startAnimator() {
if (!this._scrollAnimator.inProgress()) {
this._scrollAnimator.start()
}
}
_stopAnimator() {
this._scrollAnimator.stop()
}
_addWidgetPrefix(className) {
const componentName = this.NAME;
return (0, _inflector.dasherize)(componentName) + (className ? `-${className}` : "")
}
_getItemsSelector() {
return this.option("filter") || ""
}
_$content() {
const $element = this.$element();
const $wrapper = $element.children(".dx-template-wrapper");
return $wrapper.length ? $wrapper : $element
}
_attachEventHandlers() {
if (this.option("disabled")) {
return
}
let $element = this._$content();
let itemsSelector = this._getItemsSelector();
const allowMoveByClick = this.option("allowMoveByClick");
const data = {
direction: this.option("dragDirection"),
immediate: this.option("immediate"),
checkDropTarget: ($target, event) => {
const targetGroup = this.option("group");
const sourceGroup = this._getSourceDraggable().option("group");
const $scrollable = this._getScrollable($target);
if (this._verticalScrollHelper.isOutsideScrollable($scrollable, event) || this._horizontalScrollHelper.isOutsideScrollable($scrollable, event)) {
return false
}
return sourceGroup && sourceGroup === targetGroup
}
};
if (allowMoveByClick) {
$element = this._getArea();
_events_engine.default.on($element, POINTERDOWN_EVENT_NAME, data, this._pointerDownHandler.bind(this))
}
if (">" === itemsSelector[0]) {
itemsSelector = itemsSelector.slice(1)
}
_events_engine.default.on($element, DRAGSTART_EVENT_NAME, itemsSelector, data, this._dragStartHandler.bind(this));
_events_engine.default.on($element, DRAG_EVENT_NAME, data, this._dragMoveHandler.bind(this));
_events_engine.default.on($element, DRAGEND_EVENT_NAME, data, this._dragEndHandler.bind(this));
_events_engine.default.on($element, DRAG_ENTER_EVENT_NAME, data, this._dragEnterHandler.bind(this));
_events_engine.default.on($element, DRAGEND_LEAVE_EVENT_NAME, data, this._dragLeaveHandler.bind(this));
if (this.option("onCancelByEsc")) {
_events_engine.default.on($element, KEYDOWN_EVENT_NAME, this._keydownHandler.bind(this))
}
}
_dragElementIsCloned() {
var _this$_$dragElement;
return null === (_this$_$dragElement = this._$dragElement) || void 0 === _this$_$dragElement ? void 0 : _this$_$dragElement.hasClass(this._addWidgetPrefix("clone"))
}
_getDragTemplateArgs($element, $container) {
return {
container: (0, _element.getPublicElement)($container),
model: {
itemData: this.option("itemData"),
itemElement: (0, _element.getPublicElement)($element)
}
}
}
_createDragElement($element) {
let result = $element;
const clone = this.option("clone");
const $container = this._getContainer();
let template = this.option("dragTemplate");
if (template) {
template = this._getTemplate(template);
result = (0, _renderer.default)("<div>").appendTo($container);
template.render(this._getDragTemplateArgs($element, result))
} else if (clone) {
result = (0, _renderer.default)("<div>").appendTo($container);
$element.clone().css({
width: $element.css("width"),
height: $element.css("height")
}).appendTo(result)
}
return result.toggleClass(this._addWidgetPrefix("clone"), result.get(0) !== $element.get(0)).toggleClass("dx-rtl", this.option("rtlEnabled"))
}
_resetDragElement() {
if (this._dragElementIsCloned()) {
var _this$_$dragElement2;
null === (_this$_$dragElement2 = this._$dragElement) || void 0 === _this$_$dragElement2 || _this$_$dragElement2.remove()
} else {
this._toggleDraggingClass(false)
}
this._$dragElement = null
}
_resetSourceElement() {
this._toggleDragSourceClass(false);
this._$sourceElement = null
}
_detachEventHandlers() {
_events_engine.default.off(this._$content(), `.${DRAGGABLE}`);
_events_engine.default.off(this._getArea(), `.${DRAGGABLE}`)
}
_move(position, $element) {
(0, _translator.move)($element || this._$dragElement, position)
}
_getDraggableElement(e) {
const $sourceElement = this._getSourceElement();
if ($sourceElement) {
return $sourceElement
}
const allowMoveByClick = this.option("allowMoveByClick");
if (allowMoveByClick) {
return this.$element()
}
let $target = (0, _renderer.default)(null === e || void 0 === e ? void 0 : e.target);
const itemsSelector = this._getItemsSelector();
if (">" === itemsSelector[0]) {
const $items = this._$content().find(itemsSelector);
if (!$items.is($target)) {
$target = $target.closest($items)
}
}
return $target
}
_getSourceElement() {
const draggable = this._getSourceDraggable();
return draggable._$sourceElement
}
_pointerDownHandler(e) {
if ((0, _index.needSkipEvent)(e)) {
return
}
const position = {};
const $element = this.$element();
const {
dragDirection: dragDirection
} = this.option();
if ("horizontal" === dragDirection || "both" === dragDirection) {
position.left = e.pageX - $element.offset().left + (0, _translator.locate)($element).left - (0, _size.getWidth)($element) / 2
}
if ("vertical" === dragDirection || "both" === dragDirection) {
position.top = e.pageY - $element.offset().top + (0, _translator.locate)($element).top - (0, _size.getHeight)($element) / 2
}
this._move(position, $element);
this._getAction("onDragMove")(this._getEventArgs(e))
}
_isValidElement(event, $element) {
var _event$originalEvent;
const {
handle: handle
} = this.option();
const $target = (0, _renderer.default)(null === (_event$originalEvent = event.originalEvent) || void 0 === _event$originalEvent ? void 0 : _event$originalEvent.target);
if (handle && !$target.closest(handle).length) {
return false
}
if (!$element.length) {
return false
}
return !$element.is(".dx-state-disabled, .dx-state-disabled *")
}
_dragStartHandler(e) {
const $element = this._getDraggableElement(e);
this.dragInProgress = true;
if (!this._isValidElement(e, $element)) {
e.cancel = true;
return
}
if (this._$sourceElement) {
return
}
const dragStartArgs = this._getDragStartArgs(e, $element);
this._getAction("onDragStart")(dragStartArgs);
if (dragStartArgs.cancel) {
e.cancel = true;
return
}
this.option("itemData", dragStartArgs.itemData);
this._setSourceDraggable();
this._$sourceElement = $element;
let initialOffset = $element.offset();
if (!this._hasClonedDraggable() && this.option("autoScroll")) {
this._initScrollTop = this._getScrollableScrollTop();
this._initScrollLeft = this._getScrollableScrollLeft();
initialOffset = this._getDraggableElementOffset(initialOffset.left, initialOffset.top)
}
const $dragElement = this._$dragElement = this._createDragElement($element);
this._toggleDraggingClass(true);
this._toggleDragSourceClass(true);
this._setGestureCoverCursor($dragElement.children());
const isFixedPosition = "fixed" === $dragElement.css("position");
this._initPosition((0, _extend.extend)({}, dragStartArgs, {
dragElement: $dragElement.get(0),
initialOffset: isFixedPosition && initialOffset
}));
this._getAction("onDraggableElementShown")(_extends({}, dragStartArgs, {
dragElement: $dragElement
}));
const $area = this._getArea();
const areaOffset = this._getAreaOffset($area);
const boundOffset = this._getBoundOffset();
const areaWidth = (0, _size.getOuterWidth)($area);
const areaHeight = (0, _size.getOuterHeight)($area);
const elementWidth = (0, _size.getWidth)($dragElement);
const elementHeight = (0, _size.getHeight)($dragElement);
const startOffset_left = $dragElement.offset().left - areaOffset.left,
startOffset_top = $dragElement.offset().top - areaOffset.top;
if ($area.length) {
e.maxLeftOffset = startOffset_left - boundOffset.left;
e.maxRightOffset = areaWidth - startOffset_left - elementWidth - boundOffset.right;
e.maxTopOffset = startOffset_top - boundOffset.top;
e.maxBottomOffset = areaHeight - startOffset_top - elementHeight - boundOffset.bottom
}
if (this.option("autoScroll")) {
this._startAnimator()
}
}
_getAreaOffset($area) {
const offset = $area && _position.default.offset($area);
return offset || {
left: 0,
top: 0
}
}
_toggleDraggingClass(value) {
var _this$_$dragElement3;
null === (_this$_$dragElement3 = this._$dragElement) || void 0 === _this$_$dragElement3 || _this$_$dragElement3.toggleClass(this._addWidgetPrefix("dragging"), value)
}
_toggleDragSourceClass(value, $element) {
const $sourceElement = $element || this._$sourceElement;
null === $sourceElement || void 0 === $sourceElement || $sourceElement.toggleClass(this._addWidgetPrefix("source"), value)
}
_setGestureCoverCursor($element) {
(0, _renderer.default)(".dx-gesture-cover").css("cursor", $element.css("cursor"))
}
_getBoundOffset() {
let boundOffset = this.option("boundOffset");
if ((0, _type.isFunction)(boundOffset)) {
boundOffset = boundOffset.call(this)
}
return (0, _string.quadToObject)(boundOffset)
}
_getArea() {
let area = this.option("boundary");
if ((0, _type.isFunction)(area)) {
area = area.call(this)
}
return (0, _renderer.default)(area)
}
_getContainer() {
let {
container: container
} = this.option();
if (void 0 === container) {
container = (0, _view_port.value)()
}
return (0, _renderer.default)(container)
}
_getDraggableElementOffset(initialOffsetX, initialOffsetY) {
var _this$_startPosition, _this$_startPosition2;
const initScrollTop = this._initScrollTop;
const initScrollLeft = this._initScrollLeft;
const scrollTop = this._getScrollableScrollTop();
const scrollLeft = this._getScrollableScrollLeft();
const elementPosition = (0, _renderer.default)(this.element()).css("position");
const isFixedPosition = "fixed" === elementPosition;
const result = {
left: ((null === (_this$_startPosition = this._startPosition) || void 0 === _this$_startPosition ? void 0 : _this$_startPosition.left) ?? 0) + initialOffsetX,
top: ((null === (_this$_startPosition2 = this._startPosition) || void 0 === _this$_startPosition2 ? void 0 : _this$_startPosition2.top) ?? 0) + initialOffsetY
};
if (isFixedPosition || this._hasClonedDraggable()) {
return result
}
return {
left: (0, _type.isNumeric)(scrollLeft) ? result.left + scrollLeft - initScrollLeft : result.left,
top: (0, _type.isNumeric)(scrollTop) ? result.top + scrollTop - initScrollTop : result.top
}
}
_hasClonedDraggable() {
return this.option("clone") || this.option("dragTemplate")
}
_dragMoveHandler(e) {
this._dragMoveArgs = e;
if (!this._$dragElement) {
e.cancel = true;
return
}
const offset = this._getDraggableElementOffset(e.offset.x, e.offset.y);
this._move(offset);
this._updateScrollable(e);
const eventArgs = this._getEventArgs(e);
this._getAction("onDragMove")(eventArgs);
if (true === eventArgs.cancel) {
return
}
const targetDraggable = this._getTargetDraggable();
targetDraggable.dragMove(e, scrollBy)
}
_updateScrollable(e) {
const that = this;
if (that.option("autoScroll")) {
const mousePosition = getMousePosition(e);
const allObjects = _dom_adapter.default.elementsFromPoint(mousePosition.x, mousePosition.y, this.$element().get(0));
that._verticalScrollHelper.updateScrollable(allObjects, mousePosition);
that._horizontalScrollHelper.updateScrollable(allObjects, mousePosition)
}
}
_getScrollable($element) {
let $scrollable;
$element.parents().toArray().some((parent => {
const $parent = (0, _renderer.default)(parent);
if (this._horizontalScrollHelper.isScrollable($parent) || this._verticalScrollHelper.isScrollable($parent)) {
$scrollable = $parent;
return true
}
return false
}));
return $scrollable
}
_getScrollableScrollTop() {
var _this$_getScrollable;
return (null === (_this$_getScrollable = this._getScrollable((0, _renderer.default)(this.element()))) || void 0 === _this$_getScrollable ? void 0 : _this$_getScrollable.scrollTop()) ?? 0
}
_getScrollableScrollLeft() {
var _this$_getScrollable2;
return (null === (_this$_getScrollable2 = this._getScrollable((0, _renderer.default)(this.element()))) || void 0 === _this$_getScrollable2 ? void 0 : _this$_getScrollable2.scrollLeft()) ?? 0
}
_defaultActionArgs() {
const args = super._defaultActionArgs.apply(this, arguments);
const component = this.option("component");
if (component) {
args.component = component;
args.element = component.element()
}
return args
}
_getEventArgs(e) {
const sourceDraggable = this._getSourceDraggable();
const targetDraggable = this._getTargetDraggable();
return {
event: e,
itemData: sourceDraggable.option("itemData"),
itemElement: (0, _element.getPublicElement)(sourceDraggable._$sourceElement),
fromComponent: sourceDraggable.option("component") || sourceDraggable,
toComponent: targetDraggable.option("component") || targetDraggable,
fromData: sourceDraggable.option("data"),
toData: targetDraggable.option("data")
}
}
_getDragStartArgs(e, $itemElement) {
const args = this._getEventArgs(e);
return {
event: args.event,
itemData: args.itemData,
itemElement: $itemElement,
fromData: args.fromData
}
}
_revertItemToInitialPosition() {
!this._dragElementIsCloned() && this._move(this._initialLocate, this._$sourceElement)
}
_dragEndHandler(e) {
const d = (0, _deferred.Deferred)();
const dragEndEventArgs = this._getEventArgs(e);
const dropEventArgs = this._getEventArgs(e);
const targetDraggable = this._getTargetDraggable();
let needRevertPosition = true;
this.dragInProgress = false;
try {
this._getAction("onDragEnd")(dragEndEventArgs)
} finally {
(0, _deferred.when)((0, _deferred.fromPromise)(dragEndEventArgs.cancel)).done((cancel => {
if (!cancel) {
if (targetDraggable !== this) {
targetDraggable._getAction("onDrop")(dropEventArgs)
}
if (!dropEventArgs.cancel) {
needRevertPosition = false;
(0, _deferred.when)((0, _deferred.fromPromise)(targetDraggable.dragEnd(dragEndEventArgs))).always(d.resolve);
return
}
}
d.resolve()
})).fail(d.resolve);
d.done((() => {
if (needRevertPosition) {
this._revertItemToInitialPosition()
}
this._resetDragOptions(targetDraggable)
}))
}
}
_isTargetOverAnotherDraggable(e) {
const sourceDraggable = this._getSourceDraggable();
if (this === sourceDraggable) {
return false
}
const $dragElement = sourceDraggable._$dragElement;
const $sourceDraggableElement = sourceDraggable.$element();
const $targetDraggableElement = this.$element();
const mousePosition = getMousePosition(e);
const elements = _dom_adapter.default.elementsFromPoint(mousePosition.x, mousePosition.y, this.element());
const firstWidgetElement = elements.filter((element => {
const $element = (0, _renderer.default)(element);
if ($element.hasClass(this._addWidgetPrefix())) {
return !$element.closest($dragElement).length
}
return false
}))[0];
const $sourceElement = this._getSourceElement();
const isTargetOverItself = firstWidgetElement === $sourceDraggableElement.get(0);
const isTargetOverNestedDraggable = (0, _renderer.default)(firstWidgetElement).closest($sourceElement).length;
return !firstWidgetElement || firstWidgetElement === $targetDraggableElement.get(0) && !isTargetOverItself && !isTargetOverNestedDraggable
}
_dragEnterHandler(e) {
this._fireDragEnterEvent(e);
if (this._isTargetOverAnotherDraggable(e)) {
this._setTargetDraggable()
}
const sourceDraggable = this._getSourceDraggable();
sourceDraggable.dragEnter(e)
}
_dragLeaveHandler(e) {
this._fireDragLeaveEvent(e);
this._resetTargetDraggable();
if (this !== this._getSourceDraggable()) {
this.reset()
}
const sourceDraggable = this._getSourceDraggable();
sourceDraggable.dragLeave(e)
}
_keydownHandler(e) {
if (this.dragInProgress && "Escape" === e.key) {
this._keydownEscapeHandler(e)
}
}
_keydownEscapeHandler(e) {
var _sourceDraggable;
const $sourceElement = this._getSourceElement();
if (!$sourceElement) {
return
}
const dragCancelEventArgs = this._getEventArgs(e);
this._getAction("onDragCancel")(dragCancelEventArgs);
if (dragCancelEventArgs.cancel) {
return
}
this.dragInProgress = false;
null === (_sourceDraggable = sourceDraggable) || void 0 === _sourceDraggable || _sourceDraggable._toggleDraggingClass(false);
this._detachEventHandlers();
this._revertItemToInitialPosition();
const targetDraggable = this._getTargetDraggable();
this._resetDragOptions(targetDraggable);
this._attachEventHandlers()
}
_getAction(name) {
return this[`_${name}Action`] || this._createActionByOption(name)
}
_getAnonymousTemplateName() {
return "content"
}
_initTemplates() {
if (!this.option("contentTemplate")) {
return
}
this._templateManager.addDefaultTemplates({
content: new _empty_template.EmptyTemplate
});
super._initTemplates.apply(this, arguments)
}
_render() {
super._render();
this.$element().addClass(this._addWidgetPrefix());
const transclude = this._templateManager.anonymousTemplateName === this.option("contentTemplate");
const template = this._getTemplateByOption("contentTemplate");
if (template) {
(0, _renderer.default)(template.render({
container: this.element(),
transclude: transclude
}))
}
}
_optionChanged(args) {
const {
name: name
} = args;
switch (name) {
case "onDragStart":
case "onDragMove":
case "onDragEnd":
case "onDrop":
case "onDragEnter":
case "onDragLeave":
case "onDragCancel":
case "onDraggableElementShown":
this[`_${name}Action`] = this._createActionByOption(name);
break;
case "dragTemplate":
case "contentTemplate":
case "container":
case "clone":
case "scrollSensitivity":
case "scrollSpeed":
case "boundOffset":
case "handle":
case "group":
case "data":
case "itemData":
break;
case "allowMoveByClick":
case "dragDirection":
case "disabled":
case "boundary":
case "filter":
case "immediate":
this._resetDragElement();
this._detachEventHandlers();
this._attachEventHandlers();
break;
case "onCancelByEsc":
this._keydownHandler();
break;
case "autoScroll":
this._verticalScrollHelper.reset();
this._horizontalScrollHelper.reset();
break;
default:
super._optionChanged(args)
}
}
_getTargetDraggable() {
return targetDraggable || this
}
_getSourceDraggable() {
return sourceDraggable || this
}
_setTargetDraggable() {
const currentGroup = this.option("group");
const sourceDraggable = this._getSourceDraggable();
if (currentGroup && currentGroup === sourceDraggable.option("group")) {
targetDraggable = this
}
}
_setSourceDraggable() {
sourceDraggable = this
}
_resetSourceDraggable() {
sourceDraggable = null
}
_resetTargetDraggable() {
targetDraggable = null
}
_resetDragOptions(targetDraggable) {
this.reset();
targetDraggable.reset();
this._stopAnimator();
this._horizontalScrollHelper.reset();
this._verticalScrollHelper.reset();
this._resetDragElement();
this._resetSourceElement();
this._resetTargetDraggable();
this._resetSourceDraggable()
}
_dispose() {
super._dispose();
this._detachEventHandlers();
this._resetDragElement();
this._resetTargetDraggable();
this._resetSourceDraggable();
this._$sourceElement = null;
this._stopAnimator()
}
_fireDragEnterEvent(sourceEvent) {
const args = this._getEventArgs(sourceEvent);
this._getAction("onDragEnter")(args)
}
_fireDragLeaveEvent(sourceEvent) {
const args = this._getEventArgs(sourceEvent);
this._getAction("onDragLeave")(args)
}
}(0, _component_registrator.default)(DRAGGABLE, Draggable);
var _default = exports.default = Draggable;