react-dnd-mouse-backend
Version:
A lightweight attempt for solving the whole HTML5 DnD - svg tags compability issue
258 lines (215 loc) • 8.36 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function getEventClientOffset(e) {
return {
x: e.clientX,
y: e.clientY
};
}
var ELEMENT_NODE = 1;
function getNodeClientOffset(node) {
var el = node.nodeType === ELEMENT_NODE ? node : node.parentElement;
if (!el) {
return null;
}
var _el$getBoundingClient = el.getBoundingClientRect(),
top = _el$getBoundingClient.top,
left = _el$getBoundingClient.left;
return { x: left, y: top };
}
function isRightClick(e) {
if ('which' in e) {
return e.which === 3;
} else if ('button' in e) {
return e.button === 2;
}
return false;
}
var MouseBackend = function () {
function MouseBackend(manager) {
_classCallCheck(this, MouseBackend);
this.actions = manager.getActions();
this.monitor = manager.getMonitor();
this.registry = manager.getRegistry();
this.sourceNodes = {};
this.sourceNodesOptions = {};
this.sourcePreviewNodes = {};
this.sourcePreviewNodesOptions = {};
this.targetNodes = {};
this.targetNodeOptions = {};
this.mouseClientOffset = {};
this.getSourceClientOffset = this.getSourceClientOffset.bind(this);
this.handleWindowMoveStart = this.handleWindowMoveStart.bind(this);
this.handleWindowMoveStartCapture = this.handleWindowMoveStartCapture.bind(this);
this.handleWindowMoveCapture = this.handleWindowMoveCapture.bind(this);
this.handleWindowMoveEndCapture = this.handleWindowMoveEndCapture.bind(this);
}
_createClass(MouseBackend, [{
key: 'setup',
value: function setup() {
if (typeof window === 'undefined') {
return;
}
if (this.constructor.isSetUp) {
throw new Error('Cannot have two DnD Mouse backend at the same time');
}
this.constructor.isSetUp = true;
window.addEventListener('mousedown', this.handleWindowMoveStartCapture, true);
window.addEventListener('mousedown', this.handleWindowMoveStart);
window.addEventListener('mousemove', this.handleWindowMoveCapture, true);
window.addEventListener('mouseup', this.handleWindowMoveEndCapture, true);
}
}, {
key: 'getSourceClientOffset',
value: function getSourceClientOffset(sourceId) {
return getNodeClientOffset(this.sourceNodes[sourceId]);
}
}, {
key: 'teardown',
value: function teardown() {
if (typeof window === 'undefined') {
return;
}
this.constructor.isSetUp = false;
this.mouseClientOffset = {};
window.removeEventListener('mousedown', this.handleWindowMoveStartCapture, true);
window.removeEventListener('mousedown', this.handleWindowMoveStart);
window.removeEventListener('mousemove', this.handleWindowMoveCapture, true);
window.removeEventListener('mouseup', this.handleWindowMoveEndCapture, true);
}
}, {
key: 'connectDragSource',
value: function connectDragSource(sourceId, node) {
var _this = this;
this.sourceNodes[sourceId] = node;
var handleMoveStart = this.handleMoveStart.bind(this, sourceId);
node.addEventListener('mousedown', handleMoveStart);
return function () {
delete _this.sourceNodes[sourceId];
node.removeEventListener('mousedown', handleMoveStart);
};
}
}, {
key: 'connectDragPreview',
value: function connectDragPreview(sourceId, node, options) {
var _this2 = this;
this.sourcePreviewNodesOptions[sourceId] = options;
this.sourcePreviewNodes[sourceId] = node;
return function () {
delete _this2.sourcePreviewNodes[sourceId];
delete _this2.sourcePreviewNodesOptions[sourceId];
};
}
}, {
key: 'connectDropTarget',
value: function connectDropTarget(targetId, node) {
var _this3 = this;
this.targetNodes[targetId] = node;
return function () {
delete _this3.targetNodes[targetId];
};
}
}, {
key: 'handleWindowMoveStartCapture',
value: function handleWindowMoveStartCapture() {
this.moveStartSourceIds = [];
}
}, {
key: 'handleMoveStart',
value: function handleMoveStart(sourceId, e) {
// Ignore right mouse button.
if (isRightClick(e)) return;
this.moveStartSourceIds.unshift(sourceId);
}
}, {
key: 'handleWindowMoveStart',
value: function handleWindowMoveStart(e) {
var clientOffset = getEventClientOffset(e);
if (clientOffset) {
this.mouseClientOffset = clientOffset;
}
}
}, {
key: 'handleWindowMoveCapture',
value: function handleWindowMoveCapture(e) {
var _this4 = this;
var moveStartSourceIds = this.moveStartSourceIds;
var clientOffset = getEventClientOffset(e);
if (!clientOffset) return;
if (!this.monitor.isDragging() && this.mouseClientOffset.hasOwnProperty('x') && moveStartSourceIds && (this.mouseClientOffset.x !== clientOffset.x || this.mouseClientOffset.y !== clientOffset.y)) {
this.moveStartSourceIds = null;
this.actions.beginDrag(moveStartSourceIds, {
clientOffset: this.mouseClientOffset,
getSourceClientOffset: this.getSourceClientOffset,
publishSource: false
});
}
if (!this.monitor.isDragging()) {
return;
}
var sourceNode = this.sourceNodes[this.monitor.getSourceId()];
this.installSourceNodeRemovalObserver(sourceNode);
this.actions.publishDragSource();
e.preventDefault();
var matchingTargetIds = Object.keys(this.targetNodes).filter(function (targetId) {
var boundingRect = _this4.targetNodes[targetId].getBoundingClientRect();
return clientOffset.x >= boundingRect.left && clientOffset.x <= boundingRect.right && clientOffset.y >= boundingRect.top && clientOffset.y <= boundingRect.bottom;
});
this.actions.hover(matchingTargetIds, {
clientOffset: clientOffset
});
}
}, {
key: 'handleWindowMoveEndCapture',
value: function handleWindowMoveEndCapture(e) {
if (!this.monitor.isDragging() || this.monitor.didDrop()) {
this.moveStartSourceIds = null;
return;
}
e.preventDefault();
this.mouseClientOffset = {};
this.uninstallSourceNodeRemovalObserver();
this.actions.drop();
this.actions.endDrag();
}
}, {
key: 'installSourceNodeRemovalObserver',
value: function installSourceNodeRemovalObserver(node) {
var _this5 = this;
this.uninstallSourceNodeRemovalObserver();
this.draggedSourceNode = node;
this.draggedSourceNodeRemovalObserver = new window.MutationObserver(function () {
if (!node.parentElement) {
_this5.resurrectSourceNode();
_this5.uninstallSourceNodeRemovalObserver();
}
});
if (!node || !node.parentElement) {
return;
}
this.draggedSourceNodeRemovalObserver.observe(node.parentElement, { childList: true });
}
}, {
key: 'resurrectSourceNode',
value: function resurrectSourceNode() {
this.draggedSourceNode.style.display = 'none';
this.draggedSourceNode.removeAttribute('data-reactid');
document.body.appendChild(this.draggedSourceNode);
}
}, {
key: 'uninstallSourceNodeRemovalObserver',
value: function uninstallSourceNodeRemovalObserver() {
if (this.draggedSourceNodeRemovalObserver) {
this.draggedSourceNodeRemovalObserver.disconnect();
}
this.draggedSourceNodeRemovalObserver = null;
this.draggedSourceNode = null;
}
}]);
return MouseBackend;
}();
exports.default = MouseBackend;