resizedrag
Version:
Tiny javascript library to make DOM elements movable & resizable
180 lines (169 loc) • 6.41 kB
JavaScript
let _loaded = false;
let _callbacks = [];
const _isTouch = window.ontouchstart !== undefined;
const resizedrag = function(target, handler, onStart, onEnd) {
let config = {
dragEnabled : target.dataset.rdDragEnabled !== "false",
resizeEnabled : target.dataset.rdResizeEnabled !== "false",
dragBorderEnabled : target.dataset.rdDragBorderEnabled !== "false",
rdDragBoundary : target.dataset.rdDragBoundary === "true",
minWidth : target.dataset.rdMinWidth ? target.dataset.rdMinWidth : 5 ,
minHeight : target.dataset.rdMinHeight ? target.dataset.rdMinHeight : 5
}
let MARGINS = 4;
let edges = {
top : false,
bottom : false,
left : false,
right : false,
}
let targetElement = document.getElementById(target.id);
let clickedInstance ;
let eventHandlers = {
mousemove : function(e) {
let c = e;
if(e.touches) {
c = e.touches[0];
}
// On mouse move, dispatch the coords to all registered callbacks.
for (var i = 0; i < _callbacks.length; i++) {
_callbacks[i](c.clientX, c.clientY);
}
},
mousedown : function(e) {
e.stopPropagation();
e.preventDefault();
if (!config.dragEnabled && !config.resizeEnabled) {
return;
}
let c = e;
if (e.touches) {
c = e.touches[0];
}
isMoving = true;
let bObj = attachResizeDragCursorStyle(c.clientX,c.clientY);
clickedInstance = {
cx : c.clientX,
cy : c.clientY,
w: bObj.b.width,
h: bObj.b.height
}
isResizing = edges.right || edges.bottom || edges.top || edges.left;
if(!isResizing){
target.style["border-style"]="dashed";
target.style["border-color"]="grey";
target.style["border-width"]="2px";
}
startX = target.offsetLeft - c.clientX;
startY = target.offsetTop - c.clientY;
},
mouseup : function(e) {
if (onEnd && hasStarted) {
onEnd(target, parseInt(target.style.left), parseInt(target.style.top));
}
let c = e;
attachResizeDragCursorStyle(c.clientX,c.clientY);
isResizing = false;
isMoving = false;
hasStarted = false;
target.style["border"]="none";
}
}
// Register a global event to capture mouse moves (once).
if (!_loaded) {
document.addEventListener(_isTouch ? "touchmove" : "mousemove", eventHandlers.mousemove);
}
_loaded = true;
let isMoving = false, hasStarted = false, isResizing = false;
let startX = 0, startY = 0, lastX = 0, lastY = 0;
// On the first click and hold, record the offset of the pointer in relation
// to the point of click inside the element.
handler.addEventListener(_isTouch ? "touchstart" : "mousedown", eventHandlers.mousedown);
// On leaving click, stop moving.
document.addEventListener(_isTouch ? "touchend" : "mouseup", eventHandlers.mouseup);
// Register mouse-move callback to move the element.
_callbacks.push(function move(x, y) {
if(targetElement && !isResizing){
attachResizeDragCursorStyle(x,y);
}
if (!isMoving) {
return;
}
if (!hasStarted) {
hasStarted = true;
if (onStart) {
onStart(target, lastX, lastY);
}
}
lastX = x + startX;
lastY = y + startY;
// If boundary checking is on, don't let the element cross the viewport.
if (config.rdDragBoundary) {
if (lastX < 1 || lastX >= window.innerWidth - target.offsetWidth) {
return;
}
if (lastY < 1 || lastY >= window.innerHeight - target.offsetHeight) {
return;
}
}
if(isMoving){
if(!isResizing && config.dragEnabled){
target.style.left = lastX + "px";
target.style.top = lastY + "px";
}else{
if(config.resizeEnabled){
let b = target.getBoundingClientRect();
let bx = x - b.left;
let by = y - b.top;
if (edges.right) {
target.style.width = Math.max(bx, config.minWidth) + 'px';
}
if (edges.bottom) {
target.style.height = Math.max(by, config.minHeight) + 'px';
}
if (edges.left) {
var currentWidth = Math.max(clickedInstance.cx - x + clickedInstance.w, config.minWidth);
if (currentWidth > config.minWidth) {
target.style.width = currentWidth + 'px';
target.style.left = x + 'px';
}
}
if (edges.top) {
var currentHeight = Math.max(clickedInstance.cy - y + clickedInstance.h, config.minHeight);
if (currentHeight > config.minHeight) {
targetElement.style.height = currentHeight + 'px';
targetElement.style.top = y + 'px';
}
}
}
}
}
});
let attachResizeDragCursorStyle = function(x,y){
let b = target.getBoundingClientRect();
let eX = x - b.left;
let eY = y - b.top;
edges.top = eY < MARGINS;
edges.left = eX < MARGINS;
edges.right = eX >= b.width - MARGINS;
edges.bottom = eY >= b.height - MARGINS;
if (edges.right && edges.bottom || edges.left && edges.top) {
targetElement.style.cursor = 'nwse-resize';
} else if (edges.right && edges.top || edges.bottom && edges.left) {
targetElement.style.cursor = 'nesw-resize';
} else if (edges.right || edges.left) {
targetElement.style.cursor = 'ew-resize';
} else if (edges.bottom || edges.top) {
targetElement.style.cursor = 'ns-resize';
} else if(eX > 0 && eX < b.width && eY > 0 && eY < b.height){
targetElement.style.cursor = config.dragEnabled ?'move':'not-allowed';
}else {
targetElement.style.cursor = 'default';
}
let boundaryObj = {
b:b, bX : eX, bY : eY
}
return boundaryObj
}
}
export { resizedrag };