UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

349 lines (288 loc) • 10.4 kB
"use strict"; var $ = require("../core/renderer"), dataUtils = require("../core/element_data"), wrapToArray = require("../core/utils/array").wrapToArray, inArray = require("../core/utils/array").inArray, iteratorUtils = require("../core/utils/iterator"), contains = require("../core/utils/dom").contains, registerEvent = require("./core/event_registrator"), eventUtils = require("./utils"), GestureEmitter = require("./gesture/emitter.gesture"), registerEmitter = require("./core/emitter_registrator"); var DRAG_START_EVENT = "dxdragstart", DRAG_EVENT = "dxdrag", DRAG_END_EVENT = "dxdragend", DRAG_ENTER_EVENT = "dxdragenter", DRAG_LEAVE_EVENT = "dxdragleave", DROP_EVENT = "dxdrop", DX_DRAG_EVENTS_COUNT_KEY = "dxDragEventsCount"; var knownDropTargets = [], knownDropTargetSelectors = [], knownDropTargetConfigs = []; var dropTargetRegistration = { setup: function setup(element, data) { var knownDropTarget = inArray(element, knownDropTargets) !== -1; if (!knownDropTarget) { knownDropTargets.push(element); knownDropTargetSelectors.push([]); knownDropTargetConfigs.push(data || {}); } }, add: function add(element, handleObj) { var index = inArray(element, knownDropTargets); this.updateEventsCounter(element, handleObj.type, 1); var selector = handleObj.selector; if (inArray(selector, knownDropTargetSelectors[index]) === -1) { knownDropTargetSelectors[index].push(selector); } }, updateEventsCounter: function updateEventsCounter(element, event, value) { if ([DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DROP_EVENT].indexOf(event) > -1) { var eventsCount = dataUtils.data(element, DX_DRAG_EVENTS_COUNT_KEY) || 0; dataUtils.data(element, DX_DRAG_EVENTS_COUNT_KEY, Math.max(0, eventsCount + value)); } }, remove: function remove(element, handleObj) { this.updateEventsCounter(element, handleObj.type, -1); }, teardown: function teardown(element) { var handlersCount = dataUtils.data(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); dataUtils.removeData(element, DX_DRAG_EVENTS_COUNT_KEY); } } }; /** * @name ui events.dxdragenter * @publicName dxdragenter * @type eventType * @type_function_param1 event:event * @type_function_param1_field1 draggingElement:Node * @module events/drag */ /** * @name ui events.dxdrop * @publicName dxdrop * @type eventType * @type_function_param1 event:event * @type_function_param1_field1 draggingElement:Node * @module events/drag */ /** * @name ui events.dxdragleave * @publicName dxdragleave * @type eventType * @type_function_param1 event:event * @type_function_param1_field1 draggingElement:Node * @module events/drag */ registerEvent(DRAG_ENTER_EVENT, dropTargetRegistration); registerEvent(DRAG_LEAVE_EVENT, dropTargetRegistration); registerEvent(DROP_EVENT, dropTargetRegistration); var getItemDelegatedTargets = function getItemDelegatedTargets($element) { var dropTargetIndex = inArray($element.get(0), knownDropTargets), dropTargetSelectors = knownDropTargetSelectors[dropTargetIndex]; var $delegatedTargets = $element.find(dropTargetSelectors.join(", ")); if (inArray(undefined, dropTargetSelectors) !== -1) { $delegatedTargets = $delegatedTargets.add($element); } return $delegatedTargets; }; var getItemConfig = function getItemConfig($element) { var dropTargetIndex = inArray($element.get(0), knownDropTargets); return knownDropTargetConfigs[dropTargetIndex]; }; var getItemPosition = function getItemPosition(dropTargetConfig, $element) { if (dropTargetConfig.itemPositionFunc) { return dropTargetConfig.itemPositionFunc($element); } else { return $element.offset(); } }; var getItemSize = function getItemSize(dropTargetConfig, $element) { if (dropTargetConfig.itemSizeFunc) { return dropTargetConfig.itemSizeFunc($element); } return { width: $element.width(), height: $element.height() }; }; var DragEmitter = GestureEmitter.inherit({ ctor: function ctor(element) { this.callBase(element); this.direction = "both"; }, _init: function _init(e) { this._initEvent = e; }, _start: function _start(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 || (e.targetElements === null ? [] : knownDropTargets)); this._dropTargets = iteratorUtils.map(dropTargets, function (element) { return $(element).get(0); }); }, _move: function _move(e) { var eventData = eventUtils.eventData(e), dragOffset = this._calculateOffset(eventData); e = this._fireEvent(DRAG_EVENT, e, { offset: dragOffset }); this._processDropTargets(e); if (!e._cancelPreventDefault) { e.preventDefault(); } }, _calculateOffset: function _calculateOffset(eventData) { return { x: this._calculateXOffset(eventData), y: this._calculateYOffset(eventData) }; }, _calculateXOffset: function _calculateXOffset(eventData) { if (this.direction !== "vertical") { var offset = eventData.x - this._startEventData.x; return this._fitOffset(offset, this._maxLeftOffset, this._maxRightOffset); } return 0; }, _calculateYOffset: function _calculateYOffset(eventData) { if (this.direction !== "horizontal") { var offset = eventData.y - this._startEventData.y; return this._fitOffset(offset, this._maxTopOffset, this._maxBottomOffset); } return 0; }, _fitOffset: function _fitOffset(offset, minOffset, maxOffset) { if (minOffset != null) { offset = Math.max(offset, -minOffset); } if (maxOffset != null) { offset = Math.min(offset, maxOffset); } return offset; }, _processDropTargets: function _processDropTargets(e) { var target = this._findDropTarget(e), sameTarget = target === this._currentDropTarget; if (!sameTarget) { this._fireDropTargetEvent(e, DRAG_LEAVE_EVENT); this._currentDropTarget = target; this._fireDropTargetEvent(e, DRAG_ENTER_EVENT); } }, _fireDropTargetEvent: function _fireDropTargetEvent(event, eventName) { if (!this._currentDropTarget) { return; } var eventData = { type: eventName, originalEvent: event, draggingElement: this._$element.get(0), target: this._currentDropTarget }; eventUtils.fireEvent(eventData); }, _findDropTarget: function _findDropTarget(e) { var that = this, 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, e)) { result = delegatedTarget; } }); }); return result; }, _checkDropTargetActive: function _checkDropTargetActive(target) { var active = false; iteratorUtils.each(this._dropTargets, function (_, activeTarget) { active = active || activeTarget === target || contains(activeTarget, target); return !active; }); return active; }, _checkDropTarget: function _checkDropTarget(config, $target, e) { var isDraggingElement = $target.get(0) === this._$element.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; } return $target; }, _end: function _end(e) { var eventData = eventUtils.eventData(e); this._fireEvent(DRAG_END_EVENT, e, { offset: this._calculateOffset(eventData) }); this._fireDropTargetEvent(e, DROP_EVENT); delete this._currentDropTarget; } }); /** * @name ui events.dxdragstart * @publicName dxdragstart * @type eventType * @type_function_param1 event:event * @type_function_param1_field1 cancel:boolean * @module events/drag */ /** * @name ui events.dxdrag * @publicName dxdrag * @type eventType * @type_function_param1 event:event * @type_function_param1_field1 offset:number * @type_function_param1_field2 cancel:boolean * @module events/drag */ /** * @name ui events.dxdragend * @publicName dxdragend * @type eventType * @type_function_param1 event:event * @type_function_param1_field1 offset:number * @type_function_param1_field2 cancel:boolean * @module events/drag */ registerEmitter({ emitter: DragEmitter, events: [DRAG_START_EVENT, DRAG_EVENT, DRAG_END_EVENT] }); ///#DEBUG exports.dropTargets = knownDropTargets; ///#ENDDEBUG exports.move = DRAG_EVENT; exports.start = DRAG_START_EVENT; exports.end = DRAG_END_EVENT; exports.enter = DRAG_ENTER_EVENT; exports.leave = DRAG_LEAVE_EVENT; exports.drop = DROP_EVENT;