aboutsummaryrefslogtreecommitdiff
path: root/src/Utils.ts
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-07-08 12:37:06 -0400
committerbobzel <zzzman@gmail.com>2022-07-08 12:37:06 -0400
commit5628b585fa6356d66cf2e7454be20e3b847ad22e (patch)
tree7836fd781c3cd82c00965d22c6bdf325414ef490 /src/Utils.ts
parent146f8622d5bac2edc6b09f57c173bd057dfbcfad (diff)
fixes for drawing ink on pdf/image/etc. fixes for showing contextMenu. moved gestureOverlay into main dashboard area to avoid drawing on UI widgets. more code cleanup to put things in reasonable places and avoid importing too much stuff.
Diffstat (limited to 'src/Utils.ts')
-rw-r--r--src/Utils.ts348
1 files changed, 203 insertions, 145 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 6699aa133..528a429d0 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -1,5 +1,5 @@
import v4 = require('uuid/v4');
-import v5 = require("uuid/v5");
+import v5 = require('uuid/v5');
import { ColorState } from 'react-color';
import { Socket } from 'socket.io';
import { Colors } from './client/views/global/globalEnums';
@@ -16,7 +16,7 @@ export namespace Utils {
return new Promise((resolve, reject) => {
temporaryFileReader.onerror = () => {
temporaryFileReader.abort();
- reject(new DOMException("Problem parsing input file."));
+ reject(new DOMException('Problem parsing input file.'));
};
temporaryFileReader.onload = () => {
@@ -34,7 +34,7 @@ export namespace Utils {
return v5(seed, v5.URL);
}
- export function GetScreenTransform(ele?: HTMLElement): { scale: number, translateX: number, translateY: number } {
+ export function GetScreenTransform(ele?: HTMLElement): { scale: number; translateX: number; translateY: number } {
if (!ele) {
return { scale: 1, translateX: 1, translateY: 1 };
}
@@ -50,12 +50,12 @@ export namespace Utils {
['log', 'warn'].forEach(function (method) {
const old = (console as any)[method];
(console as any)[method] = function () {
- let stack = new Error("").stack?.split(/\n/);
+ let stack = new Error('').stack?.split(/\n/);
// Chrome includes a single "Error" line, FF doesn't.
if (stack && stack[0].indexOf('Error') === 0) {
stack = stack.slice(1);
}
- const message = (stack?.[1] || "Stack undefined!").trim();
+ const message = (stack?.[1] || 'Stack undefined!').trim();
const args = ([] as any[]).slice.apply(arguments).concat([message]);
return old.apply(console, args);
};
@@ -79,7 +79,7 @@ export namespace Utils {
}
export function CorsProxy(url: string): string {
- return prepend("/corsProxy/") + encodeURIComponent(url);
+ return prepend('/corsProxy/') + encodeURIComponent(url);
}
export function CopyText(text: string) {
@@ -88,14 +88,13 @@ export namespace Utils {
export function decimalToHexString(number: number) {
if (number < 0) {
- number = 0xFFFFFFFF + number + 1;
+ number = 0xffffffff + number + 1;
}
- return (number < 16 ? "0" : "") + number.toString(16).toUpperCase();
+ return (number < 16 ? '0' : '') + number.toString(16).toUpperCase();
}
export function colorString(color: ColorState) {
- return color.hex.startsWith("#") ?
- color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : "ff") : color.hex;
+ return color.hex.startsWith('#') ? color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff') : color.hex;
}
export function fromRGBAstr(rgba: string) {
@@ -110,8 +109,8 @@ export namespace Utils {
return { r: r, g: g, b: b, a: a };
}
- const isTransparentFunctionHack = "isTransparent(__value__)";
- export const noRecursionHack = "__noRecursion";
+ const isTransparentFunctionHack = 'isTransparent(__value__)';
+ export const noRecursionHack = '__noRecursion';
export function IsRecursiveFilter(val: string) {
return !val.includes(noRecursionHack);
}
@@ -120,18 +119,18 @@ export namespace Utils {
}
export function IsTransparentFilter() {
// bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one
- return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:check`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
+ return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:check`; // bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
}
export function IsOpaqueFilter() {
// bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one
- return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
+ return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`; // bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
}
export function PropUnsetFilter(prop: string) {
return `${prop}:any,${noRecursionHack}:unset`;
}
- export function toRGBAstr(col: { r: number, g: number, b: number, a?: number }) {
- return "rgba(" + col.r + "," + col.g + "," + col.b + (col.a !== undefined ? "," + col.a : "") + ")";
+ export function toRGBAstr(col: { r: number; g: number; b: number; a?: number }) {
+ return 'rgba(' + col.r + ',' + col.g + ',' + col.b + (col.a !== undefined ? ',' + col.a : '') + ')';
}
export function HSLtoRGB(h: number, s: number, l: number) {
@@ -140,23 +139,35 @@ export namespace Utils {
// l /= 100;
const c = (1 - Math.abs(2 * l - 1)) * s,
- x = c * (1 - Math.abs((h / 60) % 2 - 1)),
+ x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
m = l - c / 2;
let r = 0,
g = 0,
b = 0;
if (0 <= h && h < 60) {
- r = c; g = x; b = 0;
+ r = c;
+ g = x;
+ b = 0;
} else if (60 <= h && h < 120) {
- r = x; g = c; b = 0;
+ r = x;
+ g = c;
+ b = 0;
} else if (120 <= h && h < 180) {
- r = 0; g = c; b = x;
+ r = 0;
+ g = c;
+ b = x;
} else if (180 <= h && h < 240) {
- r = 0; g = x; b = c;
+ r = 0;
+ g = x;
+ b = c;
} else if (240 <= h && h < 300) {
- r = x; g = 0; b = c;
+ r = x;
+ g = 0;
+ b = c;
} else if (300 <= h && h < 360) {
- r = c; g = 0; b = x;
+ r = c;
+ g = 0;
+ b = x;
}
r = Math.round((r + m) * 255);
g = Math.round((g + m) * 255);
@@ -221,18 +232,17 @@ export namespace Utils {
export function distanceBetweenHorizontalLines(xs: number, xe: number, y: number, xs2: number, xe2: number, y2: number): [number, number[]] {
if ((xs2 <= xs && xe2 >= xs) || (xs2 <= xe && xe2 >= xe) || (xs2 >= xs && xe2 <= xe)) return [Math.abs(y - y2), [Math.max(xs, xs2), y, Math.min(xe, xe2), y]];
if (xe2 <= xs) return [Math.sqrt((xe2 - xs) * (xe2 - xs) + (y2 - y) * (y2 - y)), [xs, y, xs, y]];
- //if (xs2 > xe)
+ //if (xs2 > xe)
return [Math.sqrt((xs2 - xe) * (xs2 - xe) + (y2 - y) * (y2 - y)), [xe, y, xe, y]];
}
export function distanceBetweenVerticalLines(x: number, ys: number, ye: number, x2: number, ys2: number, ye2: number): [number, number[]] {
if ((ys2 <= ys && ye2 >= ys) || (ys2 <= ye && ye2 >= ye) || (ys2 >= ys && ye2 <= ye)) return [Math.abs(x - x2), [x, Math.max(ys, ys2), x, Math.min(ye, ye2)]];
if (ye2 <= ys) return [Math.sqrt((ye2 - ys) * (ye2 - ys) + (x2 - x) * (x2 - x)), [x, ys, x, ys]];
- //if (ys2 > ye)
+ //if (ys2 > ye)
return [Math.sqrt((ys2 - ye) * (ys2 - ye) + (x2 - x) * (x2 - x)), [x, ye, x, ye]];
}
function project(px: number, py: number, ax: number, ay: number, bx: number, by: number) {
-
if (ax === bx && ay === by) return { point: { x: ax, y: ay }, left: false, dot: 0, t: 0 };
const atob = { x: bx - ax, y: by - ay };
const atop = { x: px - ax, y: py - ay };
@@ -245,30 +255,41 @@ export namespace Utils {
return {
point: {
x: ax + atob.x * t,
- y: ay + atob.y * t
+ y: ay + atob.y * t,
},
left: dot < 1,
dot: dot,
- t: t
+ t: t,
};
}
- export function closestPtBetweenRectangles(l: number, t: number, w: number, h: number,
- l1: number, t1: number, w1: number, h1: number,
- x: number, y: number) {
+ export function closestPtBetweenRectangles(l: number, t: number, w: number, h: number, l1: number, t1: number, w1: number, h1: number, x: number, y: number) {
const r = l + w,
b = t + h;
const r1 = l1 + w1,
b1 = t1 + h1;
- const hsegs = [[l, r, t, l1, r1, t1], [l, r, b, l1, r1, t1], [l, r, t, l1, r1, b1], [l, r, b, l1, r1, b1]];
- const vsegs = [[l, t, b, l1, t1, b1], [r, t, b, l1, t1, b1], [l, t, b, r1, t1, b1], [r, t, b, r1, t1, b1]];
- const res = hsegs.reduce((closest, seg) => {
- const res = distanceBetweenHorizontalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]);
- return (res[0] < closest[0]) ? res : closest;
- }, [Number.MAX_VALUE, []] as [number, number[]]);
+ const hsegs = [
+ [l, r, t, l1, r1, t1],
+ [l, r, b, l1, r1, t1],
+ [l, r, t, l1, r1, b1],
+ [l, r, b, l1, r1, b1],
+ ];
+ const vsegs = [
+ [l, t, b, l1, t1, b1],
+ [r, t, b, l1, t1, b1],
+ [l, t, b, r1, t1, b1],
+ [r, t, b, r1, t1, b1],
+ ];
+ const res = hsegs.reduce(
+ (closest, seg) => {
+ const res = distanceBetweenHorizontalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]);
+ return res[0] < closest[0] ? res : closest;
+ },
+ [Number.MAX_VALUE, []] as [number, number[]]
+ );
const fres = vsegs.reduce((closest, seg) => {
const res = distanceBetweenVerticalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]);
- return (res[0] < closest[0]) ? res : closest;
+ return res[0] < closest[0] ? res : closest;
}, res);
const near = project(x, y, fres[1][0], fres[1][1], fres[1][2], fres[1][3]);
@@ -279,8 +300,7 @@ export namespace Utils {
const r = l + w,
b = t + h;
- x = clamp(x, l, r),
- y = clamp(y, t, b);
+ (x = clamp(x, l, r)), (y = clamp(y, t, b));
const dl = Math.abs(x - l),
dr = Math.abs(x - r),
@@ -289,18 +309,18 @@ export namespace Utils {
const m = Math.min(dl, dr, dt, db);
- return (m === dt) ? [x, t] :
- (m === db) ? [x, b] :
- (m === dl) ? [l, y] : [r, y];
+ return m === dt ? [x, t] : m === db ? [x, b] : m === dl ? [l, y] : [r, y];
}
export function GetClipboardText(): string {
- const textArea = document.createElement("textarea");
+ const textArea = document.createElement('textarea');
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
- try { document.execCommand('paste'); } catch (err) { }
+ try {
+ document.execCommand('paste');
+ } catch (err) {}
const val = textArea.value;
document.body.removeChild(textArea);
@@ -318,7 +338,7 @@ export namespace Utils {
if (logFilter !== undefined && logFilter !== message.type) {
return;
}
- const idString = (message.id || "").padStart(36, ' ');
+ const idString = (message.id || '').padStart(36, ' ');
prefix = prefix.padEnd(16, ' ');
console.log(`${prefix}: ${idString}, ${receiving ? 'receiving' : 'sending'} ${messageName} with data ${JSON.stringify(message)} `);
}
@@ -331,14 +351,14 @@ export namespace Utils {
}
export function Emit<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T) {
- log("Emit", message.Name, args, false);
+ log('Emit', message.Name, args, false);
socket.emit(message.Message, args);
}
export function EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T): Promise<any>;
export function EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn: (args: any) => any): void;
export function EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn?: (args: any) => any): void | Promise<any> {
- log("Emit", message.Name, args, false);
+ log('Emit', message.Name, args, false);
if (fn) {
socket.emit(message.Message, args, loggingCallback('Receiving', fn, message.Name));
} else {
@@ -358,30 +378,33 @@ export namespace Utils {
}
export type RoomHandler = (socket: Socket, room: string) => any;
export type UsedSockets = Socket | SocketIOClient.Socket;
- export type RoomMessage = "create or join" | "created" | "joined";
+ export type RoomMessage = 'create or join' | 'created' | 'joined';
export function AddRoomHandler(socket: Socket, message: RoomMessage, handler: RoomHandler) {
socket.on(message, room => handler(socket, room));
}
}
-export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc?: (dup: any) => void): { omit: any, extract: any } {
+export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc?: (dup: any) => void): { omit: any; extract: any } {
const omit: any = { ...obj };
const extract: any = {};
keys.forEach(key => {
extract[key] = omit[key];
delete omit[key];
});
- pattern && Array.from(Object.keys(omit)).filter(key => key.match(pattern)).forEach(key => {
- extract[key] = omit[key];
- delete omit[key];
- });
+ pattern &&
+ Array.from(Object.keys(omit))
+ .filter(key => key.match(pattern))
+ .forEach(key => {
+ extract[key] = omit[key];
+ delete omit[key];
+ });
addKeyFunc?.(omit);
return { omit, extract };
}
export function WithKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => void) {
const dup: any = {};
- keys.forEach(key => dup[key] = obj[key]);
+ keys.forEach(key => (dup[key] = obj[key]));
addKeyFunc && addKeyFunc(dup);
return dup;
}
@@ -402,31 +425,39 @@ export function timenow() {
export function incrementTitleCopy(title: string) {
const numstr = title.match(/.*(\{([0-9]*)\})+/);
- const copyNumStr = `{${1 + (numstr ? (+numstr[2]) : 0)}}`;
- return (numstr ? title.replace(numstr[1], "") : title) + copyNumStr;
+ const copyNumStr = `{${1 + (numstr ? +numstr[2] : 0)}}`;
+ return (numstr ? title.replace(numstr[1], '') : title) + copyNumStr;
}
export function formatTime(time: number) {
time = Math.round(time);
const hours = Math.floor(time / 60 / 60);
- const minutes = Math.floor(time / 60) - (hours * 60);
+ const minutes = Math.floor(time / 60) - hours * 60;
const seconds = time % 60;
- return (hours ? hours.toString() + ":" : "") + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0');
+ return (hours ? hours.toString() + ':' : '') + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0');
}
// x is furthest left, y is furthest top, r is furthest right, b is furthest bottom
-export function aggregateBounds(boundsList: { x: number, y: number, width?: number, height?: number }[], xpad: number, ypad: number) {
- const bounds = boundsList.map(b => ({ x: b.x, y: b.y, r: b.x + (b.width || 0), b: b.y + (b.height || 0) })).reduce((bounds, b) => ({
- x: Math.min(b.x, bounds.x), y: Math.min(b.y, bounds.y),
- r: Math.max(b.r, bounds.r), b: Math.max(b.b, bounds.b)
- }), { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE });
+export function aggregateBounds(boundsList: { x: number; y: number; width?: number; height?: number }[], xpad: number, ypad: number) {
+ const bounds = boundsList
+ .map(b => ({ x: b.x, y: b.y, r: b.x + (b.width || 0), b: b.y + (b.height || 0) }))
+ .reduce(
+ (bounds, b) => ({
+ x: Math.min(b.x, bounds.x),
+ y: Math.min(b.y, bounds.y),
+ r: Math.max(b.r, bounds.r),
+ b: Math.max(b.b, bounds.b),
+ }),
+ { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE }
+ );
return {
- x: bounds.x !== Number.MAX_VALUE ? bounds.x - xpad : bounds.x, y: bounds.y !== Number.MAX_VALUE ? bounds.y - ypad : bounds.y,
- r: bounds.r !== -Number.MAX_VALUE ? bounds.r + xpad : bounds.r, b: bounds.b !== -Number.MAX_VALUE ? bounds.b + ypad : bounds.b
+ x: bounds.x !== Number.MAX_VALUE ? bounds.x - xpad : bounds.x,
+ y: bounds.y !== Number.MAX_VALUE ? bounds.y - ypad : bounds.y,
+ r: bounds.r !== -Number.MAX_VALUE ? bounds.r + xpad : bounds.r,
+ b: bounds.b !== -Number.MAX_VALUE ? bounds.b + ypad : bounds.b,
};
}
-export function intersectRect(r1: { left: number, top: number, width: number, height: number },
- r2: { left: number, top: number, width: number, height: number }) {
+export function intersectRect(r1: { left: number; top: number; width: number; height: number }, r2: { left: number; top: number; width: number; height: number }) {
return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top);
}
@@ -434,36 +465,63 @@ export function percent2frac(percent: string) {
return Number(percent.substr(0, percent.length - 1)) / 100;
}
-export function numberRange(num: number) { return num > 0 && num < 1000 ? Array.from(Array(num)).map((v, i) => i) : []; }
+export function numberRange(num: number) {
+ return num > 0 && num < 1000 ? Array.from(Array(num)).map((v, i) => i) : [];
+}
-export function returnTransparent() { return "transparent"; }
+export function returnTransparent() {
+ return 'transparent';
+}
-export function returnTrue() { return true; }
+export function returnTrue() {
+ return true;
+}
-export function returnFalse() { return false; }
+export function returnFalse() {
+ return false;
+}
-export function returnAll() { return "all"; }
+export function returnAll() {
+ return 'all';
+}
-export function returnNone() { return "none"; }
+export function returnNone() {
+ return 'none';
+}
-export function returnVal(val1?: number, val2?: number) { return val1 !== undefined ? val1 : val2 !== undefined ? val2 : 0; }
+export function returnVal(val1?: number, val2?: number) {
+ return val1 !== undefined ? val1 : val2 !== undefined ? val2 : 0;
+}
-export function returnOne() { return 1; }
+export function returnOne() {
+ return 1;
+}
-export function returnZero() { return 0; }
+export function returnZero() {
+ return 0;
+}
-export function returnEmptyString() { return ""; }
+export function returnEmptyString() {
+ return '';
+}
-export function returnEmptyFilter() { return [] as string[]; }
+export function returnEmptyFilter() {
+ return [] as string[];
+}
-export function returnEmptyDoclist() { return [] as any[]; }
+export function returnEmptyDoclist() {
+ return [] as any[];
+}
export let emptyPath = [];
-export function emptyFunction() { return undefined; }
-
-export function unimplementedFunction() { throw new Error("This function is not implemented, but should be."); }
+export function emptyFunction() {
+ return undefined;
+}
+export function unimplementedFunction() {
+ throw new Error('This function is not implemented, but should be.');
+}
export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
@@ -484,7 +542,6 @@ export function DeepCopy<K, V>(source: Map<K, V>, predicate?: Predicate<K, V>) {
}
export namespace JSONUtils {
-
export function tryParse(source: string) {
let results: any;
try {
@@ -494,7 +551,6 @@ export namespace JSONUtils {
}
return results;
}
-
}
const easeInOutQuad = (currentTime: number, start: number, change: number, duration: number) => {
@@ -509,52 +565,57 @@ const easeInOutQuad = (currentTime: number, start: number, change: number, durat
};
export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number) {
- const elements = (element instanceof HTMLElement ? [element] : element);
+ const elements = element instanceof HTMLElement ? [element] : element;
const starts = elements.map(element => element.scrollTop);
const startDate = new Date().getTime();
const animateScroll = () => {
const currentDate = new Date().getTime();
const currentTime = currentDate - startDate;
- elements.map((element, i) => element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration));
+ elements.map((element, i) => (element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration)));
if (currentTime < duration) {
requestAnimationFrame(animateScroll);
} else {
- elements.forEach(element => element.scrollTop = to);
+ elements.forEach(element => (element.scrollTop = to));
}
};
animateScroll();
}
export function smoothScrollHorizontal(duration: number, element: HTMLElement | HTMLElement[], to: number) {
- const elements = (element instanceof HTMLElement ? [element] : element);
+ const elements = element instanceof HTMLElement ? [element] : element;
const starts = elements.map(element => element.scrollLeft);
const startDate = new Date().getTime();
const animateScroll = () => {
const currentDate = new Date().getTime();
const currentTime = currentDate - startDate;
- elements.map((element, i) => element.scrollLeft = easeInOutQuad(currentTime, starts[i], to - starts[i], duration));
+ elements.map((element, i) => (element.scrollLeft = easeInOutQuad(currentTime, starts[i], to - starts[i], duration)));
if (currentTime < duration) {
requestAnimationFrame(animateScroll);
} else {
- elements.forEach(element => element.scrollLeft = to);
+ elements.forEach(element => (element.scrollLeft = to));
}
};
animateScroll();
}
-export function addStyleSheet(styleType: string = "text/css") {
- const style = document.createElement("style");
+export function addStyleSheet(styleType: string = 'text/css') {
+ const style = document.createElement('style');
style.type = styleType;
const sheets = document.head.appendChild(style);
return (sheets as any).sheet;
}
-export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = ".") {
- const propText = typeof css === "string" ? css : Object.keys(css).map(p => p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p])).join(";");
- return sheet.insertRule(selectorPrefix + selector + "{" + propText + "}", sheet.cssRules.length);
+export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') {
+ const propText =
+ typeof css === 'string'
+ ? css
+ : Object.keys(css)
+ .map(p => p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p]))
+ .join(';');
+ return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length);
}
export function removeStyleSheetRule(sheet: any, rule: number) {
if (sheet.rules.length) {
@@ -573,33 +634,35 @@ export function clearStyleSheetRules(sheet: any) {
export function simulateMouseClick(element: Element | null | undefined, x: number, y: number, sx: number, sy: number, rightClick = true) {
if (!element) return;
- ["pointerdown", "pointerup"].map(event => element.dispatchEvent(
- new PointerEvent(event, {
+ ['pointerdown', 'pointerup'].map(event => {
+ const me = new PointerEvent(event, {
view: window,
bubbles: true,
cancelable: true,
button: 2,
- pointerType: "mouse",
+ pointerType: 'mouse',
clientX: x,
clientY: y,
screenX: sx,
screenY: sy,
- })));
+ });
+ (me as any).dash = true;
+ element.dispatchEvent(me);
+ });
if (rightClick) {
- const me =
- new MouseEvent("contextmenu", {
- view: window,
- bubbles: true,
- cancelable: true,
- button: 2,
- clientX: x,
- clientY: y,
- movementX: 0,
- movementY: 0,
- screenX: sx,
- screenY: sy,
- });
+ const me = new MouseEvent('contextmenu', {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ button: 2,
+ clientX: x,
+ clientY: y,
+ movementX: 0,
+ movementY: 0,
+ screenX: sx,
+ screenY: sy,
+ });
(me as any).dash = true;
element.dispatchEvent(me);
}
@@ -607,27 +670,25 @@ export function simulateMouseClick(element: Element | null | undefined, x: numbe
export function DashColor(color: string) {
try {
- return color ? Color(color.toLowerCase()) : Color("transparent");
+ return color ? Color(color.toLowerCase()) : Color('transparent');
} catch (e) {
- console.log("COLOR error:", e);
- return Color("red");
+ console.log('COLOR error:', e);
+ return Color('red');
}
}
export function lightOrDark(color: any) {
- if (color === "transparent") return "gray";
- if (color.startsWith?.("linear")) return "black";
- const nonAlphaColor = color.startsWith("#") ? (color as string).substring(0, 7) :
- color.startsWith("rgba") ? color.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : color;
+ if (color === 'transparent') return 'gray';
+ if (color.startsWith?.('linear')) return 'black';
+ const nonAlphaColor = color.startsWith('#') ? (color as string).substring(0, 7) : color.startsWith('rgba') ? color.replace(/,.[^,]*\)/, ')').replace('rgba', 'rgb') : color;
const col = DashColor(nonAlphaColor).rgb();
- const colsum = (col.red() + col.green() + col.blue());
+ const colsum = col.red() + col.green() + col.blue();
if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return Colors.DARK_GRAY;
else return Colors.WHITE;
}
-
export function getWordAtPoint(elem: any, x: number, y: number): string | undefined {
- if (elem.tagName === "INPUT") return "input";
+ if (elem.tagName === 'INPUT') return 'input';
if (elem.nodeType === elem.TEXT_NODE) {
const range = elem.ownerDocument.createRange();
range.selectNodeContents(elem);
@@ -637,12 +698,11 @@ export function getWordAtPoint(elem: any, x: number, y: number): string | undefi
range.setStart(elem, currentPos);
range.setEnd(elem, currentPos + 1);
const rangeRect = range.getBoundingClientRect();
- if (rangeRect.left <= x && rangeRect.right >= x &&
- rangeRect.top <= y && rangeRect.bottom >= y) {
- range.expand?.("word"); // doesn't exist in firefox
+ if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) {
+ range.expand?.('word'); // doesn't exist in firefox
const ret = range.toString();
range.detach();
- return (ret);
+ return ret;
}
currentPos += 1;
}
@@ -651,8 +711,7 @@ export function getWordAtPoint(elem: any, x: number, y: number): string | undefi
const range = childNode.ownerDocument.createRange();
range.selectNodeContents(childNode);
const rangeRect = range.getBoundingClientRect();
- if (rangeRect.left <= x && rangeRect.right >= x &&
- rangeRect.top <= y && rangeRect.bottom >= y) {
+ if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) {
range.detach();
const word = getWordAtPoint(childNode, x, y);
if (word) return word;
@@ -681,17 +740,17 @@ export function StopEvent(e: React.PointerEvent | React.MouseEvent) {
* Helper method for converting pixel string eg. '32px' into number eg. 32
* @param value: string with 'px' ending
* @returns value: number
- *
+ *
* Example:
* '32px' -> 32
*/
-export function numberValue(value: string | undefined):number {
+export function numberValue(value: string | undefined): number {
if (value == undefined) return 0;
return parseInt(value);
}
export function numbersAlmostEqual(num1: number, num2: number) {
- return Math.abs( num1 - num2 ) < 0.2;
+ return Math.abs(num1 - num2) < 0.2;
}
export function setupMoveUpEvents(
@@ -705,7 +764,7 @@ export function setupMoveUpEvents(
noDoubleTapTimeout?: () => void
) {
const doubleTapTimeout = 300;
- (target as any)._doubleTap = (Date.now() - (target as any)._lastTap < doubleTapTimeout);
+ (target as any)._doubleTap = Date.now() - (target as any)._lastTap < doubleTapTimeout;
(target as any)._lastTap = Date.now();
(target as any)._downX = (target as any)._lastX = e.clientX;
(target as any)._downY = (target as any)._lastY = e.clientY;
@@ -717,10 +776,9 @@ export function setupMoveUpEvents(
clearTimeout((target as any)._doubleTime);
(target as any)._doubleTime = undefined;
}
- if (moveEvent(e, [(target as any)._downX, (target as any)._downY],
- [e.clientX - (target as any)._lastX, e.clientY - (target as any)._lastY])) {
- document.removeEventListener("pointermove", _moveEvent);
- document.removeEventListener("pointerup", _upEvent);
+ if (moveEvent(e, [(target as any)._downX, (target as any)._downY], [e.clientX - (target as any)._lastX, e.clientY - (target as any)._lastY])) {
+ document.removeEventListener('pointermove', _moveEvent);
+ document.removeEventListener('pointerup', _upEvent);
}
}
(target as any)._lastX = e.clientX;
@@ -743,18 +801,18 @@ export function setupMoveUpEvents(
}
(target as any)._noClick = clickEvent(e, (target as any)._doubleTap);
}
- document.removeEventListener("pointermove", _moveEvent);
- document.removeEventListener("pointerup", _upEvent);
+ document.removeEventListener('pointermove', _moveEvent);
+ document.removeEventListener('pointerup', _upEvent);
};
const _clickEvent = (e: MouseEvent): void => {
if ((target as any)._noClick) e.stopPropagation();
- document.removeEventListener("click", _clickEvent, true);
- }
+ document.removeEventListener('click', _clickEvent, true);
+ };
if (stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
- document.addEventListener("pointermove", _moveEvent);
- document.addEventListener("pointerup", _upEvent);
- document.addEventListener("click", _clickEvent, true);
-} \ No newline at end of file
+ document.addEventListener('pointermove', _moveEvent);
+ document.addEventListener('pointerup', _upEvent);
+ document.addEventListener('click', _clickEvent, true);
+}