devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
256 lines (255 loc) • 9.47 kB
JavaScript
/**
* DevExtreme (esm/events/drag.js)
* Version: 21.1.4
* Build date: Mon Jun 21 2021
*
* Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import $ from "../core/renderer";
import {
data as elementData,
removeData
} from "../core/element_data";
import {
wrapToArray,
inArray
} from "../core/utils/array";
import * as iteratorUtils from "../core/utils/iterator";
import {
contains
} from "../core/utils/dom";
import registerEvent from "./core/event_registrator";
import {
eventData as eData,
fireEvent
} from "./utils/index";
import GestureEmitter from "./gesture/emitter.gesture";
import registerEmitter from "./core/emitter_registrator";
var DRAG_START_EVENT = "dxdragstart";
var DRAG_EVENT = "dxdrag";
var DRAG_END_EVENT = "dxdragend";
var DRAG_ENTER_EVENT = "dxdragenter";
var DRAG_LEAVE_EVENT = "dxdragleave";
var DROP_EVENT = "dxdrop";
var DX_DRAG_EVENTS_COUNT_KEY = "dxDragEventsCount";
var knownDropTargets = [];
var knownDropTargetSelectors = [];
var knownDropTargetConfigs = [];
var dropTargetRegistration = {
setup: function(element, data) {
var knownDropTarget = -1 !== inArray(element, knownDropTargets);
if (!knownDropTarget) {
knownDropTargets.push(element);
knownDropTargetSelectors.push([]);
knownDropTargetConfigs.push(data || {})
}
},
add: function(element, handleObj) {
var index = inArray(element, knownDropTargets);
this.updateEventsCounter(element, handleObj.type, 1);
var selector = handleObj.selector;
if (-1 === inArray(selector, knownDropTargetSelectors[index])) {
knownDropTargetSelectors[index].push(selector)
}
},
updateEventsCounter: function(element, event, value) {
if ([DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DROP_EVENT].indexOf(event) > -1) {
var eventsCount = elementData(element, DX_DRAG_EVENTS_COUNT_KEY) || 0;
elementData(element, DX_DRAG_EVENTS_COUNT_KEY, Math.max(0, eventsCount + value))
}
},
remove: function(element, handleObj) {
this.updateEventsCounter(element, handleObj.type, -1)
},
teardown: function(element) {
var handlersCount = elementData(element, DX_DRAG_EVENTS_COUNT_KEY);
if (!handlersCount) {
var index = inArray(element, knownDropTargets);
knownDropTargets.splice(index, 1);
knownDropTargetSelectors.splice(index, 1);
knownDropTargetConfigs.splice(index, 1);
removeData(element, DX_DRAG_EVENTS_COUNT_KEY)
}
}
};
registerEvent(DRAG_ENTER_EVENT, dropTargetRegistration);
registerEvent(DRAG_LEAVE_EVENT, dropTargetRegistration);
registerEvent(DROP_EVENT, dropTargetRegistration);
var getItemDelegatedTargets = function($element) {
var dropTargetIndex = inArray($element.get(0), knownDropTargets);
var dropTargetSelectors = knownDropTargetSelectors[dropTargetIndex].filter(selector => selector);
var $delegatedTargets = $element.find(dropTargetSelectors.join(", "));
if (-1 !== inArray(void 0, knownDropTargetSelectors[dropTargetIndex])) {
$delegatedTargets = $delegatedTargets.add($element)
}
return $delegatedTargets
};
var getItemConfig = function($element) {
var dropTargetIndex = inArray($element.get(0), knownDropTargets);
return knownDropTargetConfigs[dropTargetIndex]
};
var getItemPosition = function(dropTargetConfig, $element) {
if (dropTargetConfig.itemPositionFunc) {
return dropTargetConfig.itemPositionFunc($element)
} else {
return $element.offset()
}
};
var getItemSize = function(dropTargetConfig, $element) {
if (dropTargetConfig.itemSizeFunc) {
return dropTargetConfig.itemSizeFunc($element)
}
return {
width: $element.get(0).getBoundingClientRect().width,
height: $element.get(0).getBoundingClientRect().height
}
};
var DragEmitter = GestureEmitter.inherit({
ctor: function(element) {
this.callBase(element);
this.direction = "both"
},
_init: function(e) {
this._initEvent = e
},
_start: function(e) {
e = this._fireEvent(DRAG_START_EVENT, this._initEvent);
this._maxLeftOffset = e.maxLeftOffset;
this._maxRightOffset = e.maxRightOffset;
this._maxTopOffset = e.maxTopOffset;
this._maxBottomOffset = e.maxBottomOffset;
var dropTargets = wrapToArray(e.targetElements || (null === e.targetElements ? [] : knownDropTargets));
this._dropTargets = iteratorUtils.map(dropTargets, (function(element) {
return $(element).get(0)
}))
},
_move: function(e) {
var eventData = eData(e);
var dragOffset = this._calculateOffset(eventData);
e = this._fireEvent(DRAG_EVENT, e, {
offset: dragOffset
});
this._processDropTargets(e);
if (!e._cancelPreventDefault) {
e.preventDefault()
}
},
_calculateOffset: function(eventData) {
return {
x: this._calculateXOffset(eventData),
y: this._calculateYOffset(eventData)
}
},
_calculateXOffset: function(eventData) {
if ("vertical" !== this.direction) {
var offset = eventData.x - this._startEventData.x;
return this._fitOffset(offset, this._maxLeftOffset, this._maxRightOffset)
}
return 0
},
_calculateYOffset: function(eventData) {
if ("horizontal" !== this.direction) {
var offset = eventData.y - this._startEventData.y;
return this._fitOffset(offset, this._maxTopOffset, this._maxBottomOffset)
}
return 0
},
_fitOffset: function(offset, minOffset, maxOffset) {
if (null != minOffset) {
offset = Math.max(offset, -minOffset)
}
if (null != maxOffset) {
offset = Math.min(offset, maxOffset)
}
return offset
},
_processDropTargets: function(e) {
var target = this._findDropTarget(e);
var sameTarget = target === this._currentDropTarget;
if (!sameTarget) {
this._fireDropTargetEvent(e, DRAG_LEAVE_EVENT);
this._currentDropTarget = target;
this._fireDropTargetEvent(e, DRAG_ENTER_EVENT)
}
},
_fireDropTargetEvent: function(event, eventName) {
if (!this._currentDropTarget) {
return
}
var eventData = {
type: eventName,
originalEvent: event,
draggingElement: this._$element.get(0),
target: this._currentDropTarget
};
fireEvent(eventData)
},
_findDropTarget: function(e) {
var that = this;
var result;
iteratorUtils.each(knownDropTargets, (function(_, target) {
if (!that._checkDropTargetActive(target)) {
return
}
var $target = $(target);
iteratorUtils.each(getItemDelegatedTargets($target), (function(_, delegatedTarget) {
var $delegatedTarget = $(delegatedTarget);
if (that._checkDropTarget(getItemConfig($target), $delegatedTarget, $(result), e)) {
result = delegatedTarget
}
}))
}));
return result
},
_checkDropTargetActive: function(target) {
var active = false;
iteratorUtils.each(this._dropTargets, (function(_, activeTarget) {
active = active || activeTarget === target || contains(activeTarget, target);
return !active
}));
return active
},
_checkDropTarget: function(config, $target, $prevTarget, e) {
var isDraggingElement = $target.get(0) === $(e.target).get(0);
if (isDraggingElement) {
return false
}
var targetPosition = getItemPosition(config, $target);
if (e.pageX < targetPosition.left) {
return false
}
if (e.pageY < targetPosition.top) {
return false
}
var targetSize = getItemSize(config, $target);
if (e.pageX > targetPosition.left + targetSize.width) {
return false
}
if (e.pageY > targetPosition.top + targetSize.height) {
return false
}
if ($prevTarget.length && $prevTarget.closest($target).length) {
return false
}
if (config.checkDropTarget && !config.checkDropTarget($target, e)) {
return false
}
return $target
},
_end: function(e) {
var eventData = eData(e);
this._fireEvent(DRAG_END_EVENT, e, {
offset: this._calculateOffset(eventData)
});
this._fireDropTargetEvent(e, DROP_EVENT);
delete this._currentDropTarget
}
});
registerEmitter({
emitter: DragEmitter,
events: [DRAG_START_EVENT, DRAG_EVENT, DRAG_END_EVENT]
});
export {
DRAG_EVENT as move, DRAG_START_EVENT as start, DRAG_END_EVENT as end, DRAG_ENTER_EVENT as enter, DRAG_LEAVE_EVENT as leave, DROP_EVENT as drop
};