svelte-gantt
Version:
Interactive JavaScript Gantt chart/resource booking component
140 lines (139 loc) • 4.75 kB
JavaScript
import { getRelativePos, getRelativePosition } from '../utils/dom';
import { getContext } from 'svelte';
export function useCreateTask() {
const { columnService, utils } = getContext('services');
return function createTaskActionBound(node, options) {
return createTaskAction(node, {
columnService,
utils,
...options,
});
};
}
const MIN_DRAG_X = 2;
const MIN_DRAG_Y = 2;
function createTaskAction(node, options) {
let startX;
let startFrom;
let mouseStartRight;
let direction;
let initialX;
let initialY;
let triggered = false;
/** dragging will not activate around the edges */
let deadZone = 10;
const container = () => options.container;
function isNearEdge(x, y) {
const rect = options.boundsContainer.getBoundingClientRect();
const nearBottomEdge = y - rect.top >= rect.height - deadZone;
const nearRightEdge = x - rect.left >= rect.width - deadZone;
return nearBottomEdge || nearRightEdge;
}
function onMousedown(event) {
if (!options.enabled) {
return;
}
event.stopPropagation();
event.preventDefault();
if (isNearEdge(event.clientX, event.clientY)) {
return;
}
const [mousePosX, _] = getRelativePosition(container(), event);
const from = startFrom = options.utils.roundTo(options.columnService.getDateByPosition(mousePosX));
const x = startX = options.columnService.getPositionByDate(from) | 0;
const width = 0;
initialX = event.clientX;
initialY = event.clientY;
mouseStartRight = x + width;
window.addEventListener('pointermove', onMousemove, false);
window.addEventListener('pointerup', onMouseup);
}
;
function onMousemove(event) {
if (!triggered) {
if (Math.abs(event.clientX - initialX) > MIN_DRAG_X || Math.abs(event.clientY - initialY) > MIN_DRAG_Y) {
triggered = true;
}
else {
return;
}
}
event.preventDefault();
const { x, width, y } = getValues(event);
options.onMove({
from: startFrom,
to: startFrom,
x,
width,
y,
});
}
;
function getValues(event) {
const mousePos = getRelativePos(container(), event);
const x = startX;
const width = 0;
let resultX;
let resultWidth;
if (direction === 'left') {
if (mouseStartRight - mousePos.x <= 0) {
direction = 'right';
resultX = mouseStartRight;
resultWidth = mouseStartRight - mousePos.x;
mouseStartRight = mouseStartRight + width;
}
else {
resultX = mousePos.x;
resultWidth = mouseStartRight - mousePos.x;
}
}
else { // if (direction === 'right')
//resize right
if (mousePos.x - x <= 0) {
direction = 'left';
resultX = mousePos.x;
resultWidth = mousePos.x - x;
mouseStartRight = x;
}
else {
resultX = x;
resultWidth = mousePos.x - x;
}
}
return { x: resultX, width: resultWidth, y: mousePos.y };
}
function onMouseup(event) {
window.removeEventListener('pointerup', onMouseup);
window.removeEventListener('pointermove', onMousemove, false);
if (triggered) {
const { x, width, y } = getValues(event);
const newFrom = options.utils.roundTo(options.columnService.getDateByPosition(x));
const newTo = options.utils.roundTo(options.columnService.getDateByPosition(x + width));
const newLeft = options.columnService.getPositionByDate(newFrom) | 0;
const newRight = options.columnService.getPositionByDate(newTo) | 0;
options.onEnd({
from: newFrom,
to: newTo,
x: newLeft,
width: newRight - newLeft,
y,
});
}
mouseStartRight = null;
initialX = null;
initialY = null;
triggered = false;
}
;
node.addEventListener('pointerdown', onMousedown);
return {
destroy() {
node.removeEventListener('pointerdown', onMousedown);
window.removeEventListener('pointermove', onMousemove);
window.removeEventListener('pointerup', onMouseup);
},
update(opts) {
Object.assign(options, opts);
},
};
}