Files
rio/frontend/code/utils.ts
2024-04-27 17:38:23 +02:00

126 lines
3.2 KiB
TypeScript

import { componentsByElement } from './componentManagement';
export class AsyncQueue<T> {
private waitingForValue: ((value: T) => void)[] = [];
private values: T[] = [];
push(value: T): void {
// If someone is waiting for a value, give it to them
let notifyFirstWaiter = this.waitingForValue.shift();
if (notifyFirstWaiter !== undefined) {
notifyFirstWaiter(value);
return;
}
// Otherwise, push it onto the stack
this.values.push(value);
}
async get(): Promise<T> {
// If a value exists in the queue, just return that
let value = this.values.shift();
if (value !== undefined) {
return value;
}
// Otherwise, create a Promise that will be resolved when a new value is
// added to the queue
let waitForValue = new Promise((resolve: (value: T) => void) => {
this.waitingForValue.push(resolve);
});
return await waitForValue;
}
}
export function commitCss(element: HTMLElement): void {
element.offsetHeight;
}
export function disableTransitions(element: HTMLElement) {
element.style.transition = 'none';
element.offsetHeight;
}
export function enableTransitions(element: HTMLElement) {
element.style.removeProperty('transition');
element.offsetHeight;
}
export function withoutTransitions(
element: HTMLElement,
func: () => void
): void {
disableTransitions(element);
func();
enableTransitions(element);
}
/// Asynchronously sleeps for the given number of seconds.
export async function sleep(durationInSeconds: number): Promise<void> {
await new Promise((resolve, reject) =>
setTimeout(resolve, durationInSeconds * 1000)
);
}
export function reprElement(element: Element): string {
let chunks = [element.tagName.toLowerCase()];
for (let attr of element.attributes) {
chunks.push(`${attr.name}=${JSON.stringify(attr.value)}`);
}
return `<${chunks.join(' ')}>`;
}
/// Returns an array containing all numbers from `start` (inclusive) to `end`
/// (exclusive).
export function range(start: number, end: number): number[] {
let result: number[] = [];
for (let ii = start; ii < end; ii++) {
result.push(ii);
}
return result;
}
/// Returns the first argument that isn't `undefined`.
export function firstDefined(...args: any[]): any {
for (let arg of args) {
if (arg !== undefined) {
return arg;
}
}
return undefined;
}
/// Copies the given text to the clipboard
export function copyToClipboard(text: string): void {
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
}
/// Checks if there's an #url-fragment, and if so, scrolls the corresponding
/// ScrollTarget into view
export function scrollToUrlFragment(): void {
let fragment = window.location.hash.substring(1);
if (!fragment) {
return;
}
let element = document.getElementById(fragment);
if (element === null) {
return;
}
element.scrollIntoView();
}