debian-mirror-gitlab/app/assets/javascripts/test_utils/simulate_drag.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

190 lines
4.1 KiB
JavaScript
Raw Normal View History

2017-08-17 22:00:37 +05:30
function simulateEvent(el, type, options = {}) {
let event;
if (!el) return null;
2019-12-04 20:38:33 +05:30
if (/^(pointer|mouse)/.test(type)) {
event = el.ownerDocument.createEvent('MouseEvent');
2018-12-13 13:39:08 +05:30
event.initMouseEvent(
type,
true,
true,
el.ownerDocument.defaultView,
options.button,
options.screenX,
options.screenY,
options.clientX,
options.clientY,
options.ctrlKey,
options.altKey,
options.shiftKey,
options.metaKey,
options.button,
el,
);
2017-08-17 22:00:37 +05:30
} else {
event = el.ownerDocument.createEvent('CustomEvent');
2018-12-13 13:39:08 +05:30
event.initCustomEvent(
type,
true,
true,
el.ownerDocument.defaultView,
options.button,
options.screenX,
options.screenY,
options.clientX,
options.clientY,
options.ctrlKey,
options.altKey,
options.shiftKey,
options.metaKey,
options.button,
el,
);
2017-08-17 22:00:37 +05:30
event.dataTransfer = {
data: {},
setData(key, val) {
this.data[key] = val;
},
getData(key) {
return this.data[key];
},
};
}
if (el.dispatchEvent) {
el.dispatchEvent(event);
} else if (el.fireEvent) {
el.fireEvent(`on${type}`, event);
}
return event;
}
function isLast(target) {
2018-12-13 13:39:08 +05:30
const el =
typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
2018-11-08 19:23:39 +05:30
const { children } = el;
2017-08-17 22:00:37 +05:30
return children.length - 1 === target.index;
}
function getTarget(target) {
2018-12-13 13:39:08 +05:30
const el =
typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
2018-11-08 19:23:39 +05:30
const { children } = el;
2017-08-17 22:00:37 +05:30
return (
children[target.index] ||
children[target.index === 'first' ? 0 : -1] ||
children[target.index === 'last' ? children.length - 1 : -1] ||
el
);
}
function getRect(el) {
const rect = el.getBoundingClientRect();
const width = rect.right - rect.left;
2018-12-13 13:39:08 +05:30
const height = rect.bottom - rect.top + 10;
2017-08-17 22:00:37 +05:30
return {
x: rect.left,
y: rect.top,
2018-12-13 13:39:08 +05:30
cx: rect.left + width / 2,
cy: rect.top + height / 2,
2017-08-17 22:00:37 +05:30
w: width,
h: height,
hw: width / 2,
wh: height / 2,
};
}
export default function simulateDrag(options) {
const { to, from } = options;
to.el = to.el || from.el;
const fromEl = getTarget(from);
const toEl = getTarget(to);
const firstEl = getTarget({
el: to.el,
index: 'first',
});
const lastEl = getTarget({
el: options.to.el,
index: 'last',
});
const fromRect = getRect(fromEl);
const toRect = getRect(toEl);
const firstRect = getRect(firstEl);
const lastRect = getRect(lastEl);
const duration = options.duration || 1000;
2019-12-04 20:38:33 +05:30
simulateEvent(fromEl, 'pointerdown', {
2017-08-17 22:00:37 +05:30
button: 0,
clientX: fromRect.cx,
clientY: fromRect.cy,
});
if (options.ontap) options.ontap();
window.SIMULATE_DRAG_ACTIVE = 1;
if (options.to.index === 0) {
toRect.cy = firstRect.y;
} else if (isLast(options.to)) {
toRect.cy = lastRect.y + lastRect.h + 50;
}
2022-01-26 12:08:38 +05:30
let startTime;
// Called within dragFn when the drag should finish
const finishFn = () => {
if (options.ondragend) options.ondragend();
if (options.performDrop) {
simulateEvent(toEl, 'mouseup');
}
window.SIMULATE_DRAG_ACTIVE = 0;
};
const dragFn = (timestamp) => {
if (!startTime) {
startTime = timestamp;
}
const elapsed = timestamp - startTime;
// Make sure that progress maxes at 1
const progress = Math.min(elapsed / duration, 1);
2018-12-13 13:39:08 +05:30
const x = fromRect.cx + (toRect.cx - fromRect.cx) * progress;
2021-01-03 14:25:43 +05:30
const y = fromRect.cy + (toRect.cy - fromRect.cy + options.extraHeight) * progress;
2017-08-17 22:00:37 +05:30
const overEl = fromEl.ownerDocument.elementFromPoint(x, y);
2019-12-04 20:38:33 +05:30
simulateEvent(overEl, 'pointermove', {
2017-08-17 22:00:37 +05:30
clientX: x,
clientY: y,
});
if (progress >= 1) {
2022-01-26 12:08:38 +05:30
// finish on next frame, so we can pause in the correct position for a frame
requestAnimationFrame(finishFn);
} else {
requestAnimationFrame(dragFn);
2017-08-17 22:00:37 +05:30
}
2022-01-26 12:08:38 +05:30
};
// Start the drag animation
requestAnimationFrame(dragFn);
2017-08-17 22:00:37 +05:30
return {
target: fromEl,
fromList: fromEl.parentNode,
toList: toEl.parentNode,
};
}