UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

196 lines (195 loc) 7.34 kB
/** * DevExtreme (ui/draggable.js) * Version: 18.1.3 * Build date: Tue May 15 2018 * * Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var $ = require("../core/renderer"), window = require("../core/utils/window").getWindow(), eventsEngine = require("../events/core/events_engine"), stringUtils = require("../core/utils/string"), registerComponent = require("../core/component_registrator"), translator = require("../animation/translator"), dasherize = require("../core/utils/inflector").dasherize, extend = require("../core/utils/extend").extend, DOMComponent = require("../core/dom_component"), eventUtils = require("../events/utils"), pointerEvents = require("../events/pointer"), dragEvents = require("../events/drag"), positionUtils = require("../animation/position"), isFunction = require("../core/utils/type").isFunction, noop = require("../core/utils/common").noop; var DRAGGABLE = "dxDraggable", DRAGSTART_EVENT_NAME = eventUtils.addNamespace(dragEvents.start, DRAGGABLE), DRAG_EVENT_NAME = eventUtils.addNamespace(dragEvents.move, DRAGGABLE), DRAGEND_EVENT_NAME = eventUtils.addNamespace(dragEvents.end, DRAGGABLE), POINTERDOWN_EVENT_NAME = eventUtils.addNamespace(pointerEvents.down, DRAGGABLE), DRAGGABLE_CLASS = dasherize(DRAGGABLE), DRAGGABLE_DRAGGING_CLASS = DRAGGABLE_CLASS + "-dragging"; var Draggable = DOMComponent.inherit({ _getDefaultOptions: function() { return extend(this.callBase(), { onDragStart: noop, onDrag: noop, onDragEnd: noop, immediate: true, direction: "both", area: window, boundOffset: 0, allowMoveByClick: false }) }, _init: function() { this.callBase(); this._attachEventHandlers() }, _attachEventHandlers: function() { if (this.option("disabled")) { return } var $element = this.$element().css("position", "absolute"), eventHandlers = {}, allowMoveByClick = this.option("allowMoveByClick"); eventHandlers[DRAGSTART_EVENT_NAME] = this._dragStartHandler.bind(this); eventHandlers[DRAG_EVENT_NAME] = this._dragHandler.bind(this); eventHandlers[DRAGEND_EVENT_NAME] = this._dragEndHandler.bind(this); if (allowMoveByClick) { eventHandlers[POINTERDOWN_EVENT_NAME] = this._pointerDownHandler.bind(this); $element = this._getArea() } eventsEngine.on($element, eventHandlers, { direction: this.option("direction"), immediate: this.option("immediate") }) }, _detachEventHandlers: function() { eventsEngine.off(this.$element(), "." + DRAGGABLE); eventsEngine.off(this._getArea(), "." + DRAGGABLE) }, _move: function(position) { translator.move(this.$element(), position) }, _pointerDownHandler: function(e) { if (eventUtils.needSkipEvent(e)) { return } var areaOffset = this._getAreaOffset($(e.currentTarget)), direction = this.option("direction"), position = {}; if ("horizontal" === direction || "both" === direction) { position.left = e.pageX - this.$element().width() / 2 - areaOffset.left } if ("vertical" === direction || "both" === direction) { position.top = e.pageY - this.$element().height() / 2 - areaOffset.top } this._move(position); this._getAction("onDrag")({ event: e }) }, _dragStartHandler: function(e) { var $element = this.$element(); if ($element.is(".dx-state-disabled, .dx-state-disabled *")) { e.cancel = true; return } var $area = this._getArea(), areaOffset = this._getAreaOffset($area), boundOffset = this._getBoundOffset(), areaWidth = $area.outerWidth(), areaHeight = $area.outerHeight(), elementWidth = $element.width(), elementHeight = $element.height(); this._toggleDraggingClass(true); var startOffset = { left: $element.offset().left - areaOffset.left, top: $element.offset().top - areaOffset.top }; this._startPosition = translator.locate($element); 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; this._getAction("onDragStart")({ event: e }) }, _getAreaOffset: function($area) { var offset = $area && positionUtils.offset($area); return offset ? offset : { left: 0, top: 0 } }, _toggleDraggingClass: function(value) { this.$element().toggleClass(DRAGGABLE_DRAGGING_CLASS, value) }, _getBoundOffset: function() { var boundOffset = this.option("boundOffset"); if (isFunction(boundOffset)) { boundOffset = boundOffset.call(this) } return stringUtils.quadToObject(boundOffset) }, _getArea: function() { var area = this.option("area"); if (isFunction(area)) { area = area.call(this) } return $(area) }, _dragHandler: function(e) { var offset = e.offset, startPosition = this._startPosition; this._move({ left: startPosition.left + offset.x, top: startPosition.top + offset.y }); this._getAction("onDrag")({ event: e }) }, _dragEndHandler: function(e) { this._toggleDraggingClass(false); this._getAction("onDragEnd")({ event: e }) }, _getAction: function(name) { return this["_" + name + "Action"] || this._createActionByOption(name) }, _render: function() { this.callBase(); this.$element().addClass(DRAGGABLE_CLASS) }, _optionChanged: function(args) { var name = args.name; switch (name) { case "onDragStart": case "onDrag": case "onDragEnd": this["_" + name + "Action"] = this._createActionByOption(name); break; case "allowMoveByClick": case "direction": case "disabled": this._detachEventHandlers(); this._attachEventHandlers(); break; case "boundOffset": case "area": break; default: this.callBase(args) } }, _dispose: function() { this.callBase(); this._detachEventHandlers() } }); registerComponent(DRAGGABLE, Draggable); module.exports = Draggable;