File size: 5,464 Bytes
6f25f68 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
/**
* 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
];
};
|