benjamin-paine's picture
initial commit
6f25f68
raw
history blame
5.46 kB
/**
* Check if an object is 'empty'.
*
* @param object $o The object to check.o
* @return bool True if the object is empty.
*/
export let isEmpty = (o) => {
return (
o === null ||
o === undefined ||
o === '' ||
o === 'null' ||
(Array.isArray(o) && o.length === 0) ||
(typeof o === 'object' &&
o.constructor.name === 'Object' &&
Object.getOwnPropertyNames(o).length === 0)
);
};
/**
* Merge multiple typed arrays into a single typed array.
* Assumes that all the arrays are of the same type.
*
* @param {Array<TypedArray>} arrays - The arrays to merge. Any kind of typed array is allowed.
* @returns {TypedArray} - The merged typed array.
*/
export let mergeTypedArrays = (arrays) => {
let totalLength = arrays.reduce((acc, array) => acc + array.length, 0);
let result = new arrays[0].constructor(totalLength);
let offset = 0;
arrays.forEach((array) => {
result.set(array, offset);
offset += array.length;
});
return result;
}
/**
* Binds a method to window mousemove, and then unbinds it when released
* or when the mouse leaves the window.
*/
export let bindPointerUntilRelease = (callback, releaseCallback = null) => {
let onWindowPointerMove = (e) => {
callback(e);
}
let onWindowPointerUpOrLeave = (e) => {
// In chrome, window.mouseleave is triggered when the mouse leaves the window.
// In firefox, window.mouseleave is triggered when the mouse leaves any element, so we need to check if the target is the document.
if (e.type === "mouseleave" && (e.target !== null && e.target !== undefined && e.target.tagName !== "HTML")) {
return;
}
if (!isEmpty(releaseCallback)) {
releaseCallback(e);
}
window.removeEventListener("mouseup", onWindowPointerUpOrLeave, true);
window.removeEventListener("mouseleave", onWindowPointerUpOrLeave, true);
window.removeEventListener("touchend", onWindowPointerUpOrLeave, true);
window.removeEventListener("mousemove", onWindowPointerMove, true);
window.removeEventListener("touchmove", onWindowPointerMove, true);
}
window.addEventListener("mouseup", onWindowPointerUpOrLeave, true);
window.addEventListener("mouseleave", onWindowPointerUpOrLeave, true);
window.addEventListener("touchend", onWindowPointerUpOrLeave, true);
window.addEventListener("mousemove", onWindowPointerMove, true);
window.addEventListener("touchmove", onWindowPointerMove, true);
};
/**
* Binds drag events to an element.
* The callback is called with an object containing the following properties:
* - start: The starting point of the drag.
* - x: The x coordinate.
* - y: The y coordinate.
* - current: The current point of the drag.
* - x: The x coordinate.
* - y: The y coordinate.
* - delta: The difference between the current and starting points.
* - x: The x coordinate.
* - y: The y coordinate.
* - startEvent: The event that started the drag.
* - moveEvent: The event that triggered the callback.
* The releaseCallback is called when the drag is released.
*/
export let bindPointerDrag = (element, startCallback, callback, releaseCallback = null) => {
const pointerStart = (e) => {
if (e.type === "mousedown" && e.button !== 0) {
return;
}
e.preventDefault();
const startPosition = e.type === "mousedown" ? e : e.touches[0];
const startPoint = {x: startPosition.clientX, y: startPosition.clientY};
if (!isEmpty(startCallback)) {
startCallback({
start: startPoint,
startEvent: e
});
}
bindPointerUntilRelease(
(e2) => {
const currentPosition = e2.type === "mousemove" ? e2 : e2.touches[0];
const currentPoint = {x: currentPosition.clientX, y: currentPosition.clientY};
const delta = {x: currentPoint.x - startPoint.x, y: currentPoint.y - startPoint.y};
callback({
start: startPoint,
current: currentPoint,
delta: delta,
startEvent: e,
moveEvent: e2
});
},
(e2) => {
if (!isEmpty(releaseCallback)) {
releaseCallback({
start: startPoint,
startEvent: e,
releaseEvent: e2
});
}
}
);
};
element.addEventListener("mousedown", pointerStart);
element.addEventListener("touchstart", pointerStart);
};
/**
* Replaces all quotes in a string with standard quotes.
* @param {string} text - The text to replace quotes in.
* @returns {string} - The text with quotes replaced.
*/
export let replaceQuotes = (text) => {
return text.replaceAll("β€œ", "\"")
.replaceAll("”", "\"")
.replaceAll("β€˜", "'")
.replaceAll("’", "'");
};
/**
* Converts a hex color to an rgb color.
* @param {string} hex - The hex color to convert.
* @returns {array} - The rgb color.
*/
export let hexToRgb = (hex) => {
let bigint = parseInt(hex.replace("#", ""), 16);
return [
(bigint >> 16) & 255,
(bigint >> 8) & 255,
bigint & 255
];
};