// @ts-check
///
///
///
///
///
///
"use strict";
/**
* @name Celestra
* @version 6.4.0 browser
* @author Ferenc Czigler
* @see https://github.com/Serrin/Celestra/
* @license MIT https://opensource.org/licenses/MIT
*/
const VERSION = "Celestra v6.4.0 browser";
/** TS types */
/**
* @description Map-like object with string or number or symbol keys.
*
* @internal
* */
type MapLike = {[key: string]: any; [key: number]: any; [key: symbol]: any; };
/**
* @description Array-like object.
*
* @internal
* */
type ArrayLike = { length: number; [n: number]: any; };
/* interface ArrayLike { length: number; [n: number]: T; }; */
/**
* @description Set-like object.
*
* @internal
* */
/*
type SetLike ={
readonly size: number;
has(value: T): boolean;
};
*/
/**
* @description Number-like object.
*
* @internal
* */
type NumberLike = number | bigint;
/**
* @description Iterable and Iterator types.
*
* @internal
*/
type IterableAndIterator =
Iterable | Iterator | IterableIterator;
/**
* @description Iterable and Iterator and Array-like types.
*
* @internal
*/
type IterableAndIteratorAndArrayLike =
Iterable | Iterator | IterableIterator | ArrayLike;
/**
* @description Iterable and Iterator and Generator types.
*
* @internal
*/
type IteratorReturn =
Iterable | IteratorResult | Generator;
/**
* @description Type for undefined and null values.
*
* @internal
*/
type Nullish = undefined | null;
/*
built-in type:
type NonNullable = number | boolean | string | symbol | object | Function;
*/
/**
* @description Not null or undefined or object or function.
*
* @internal
*/
type NonNullablePrimitive = number | bigint | boolean | string | symbol;
/**
* @description Not object or function.
*
* @internal
*/
type Primitive = null | undefined | number | bigint | boolean | string | symbol;
/**
* Generic comparable types.
*
* @internal
*/
type Comparable = number | bigint | string | boolean;
/**
* @description Object key type.
*
* @internal
*/
type PropertyKey = string | symbol;
/**
* @description Primitive types.
*
* @internal
*/
type TypeOfTag =
| "null" | "undefined"
| "number" | "bigint" | "boolean" | "string" | "symbol"
| "object" | "function";
/**
* @description TypedArray types.
*
* @internal
*/
type TypedArray =
| Int8Array | Uint8Array | Uint8ClampedArray
| Int16Array | Uint16Array
| Int32Array | Uint32Array
| Float32Array | Float64Array
| BigInt64Array | BigUint64Array
| (typeof globalThis extends { Float16Array: infer F } ? F : never);
/**
* @description ClearCookiesOptions object type.
*
* @internal
*/
type ClearCookiesOptions = {
path?: string | undefined;
domain?: string | undefined;
secure?: boolean | undefined;
SameSite?: string | undefined;
HttpOnly?: boolean | undefined;
};
/** polyfills **/
/* globalThis; */
(function (global) {
if (!global.globalThis) {
if (Object.defineProperty) {
Object.defineProperty(global, "globalThis", {
configurable: true, enumerable: false, value: global, writable: true
});
} else {
global.globalThis = global;
}
}
})(typeof this === "object" ? this : Function("return this")());
/* Math.sumPrecise(); */
if (!("sumPrecise" in Math)) {
// @ts-ignore
Math.sumPrecise = function sumPrecise ([...array]): number {
/* empty iterator */
if (array.length === 0) { return -0; }
/* iterator with items */
if (array.every((value: unknown): boolean => typeof value === "number")) {
/* return NaN + Infinity + -Infinity */
let inf = array.indexOf(Infinity) >- 1;
let negInf = array.indexOf(-Infinity) > -1;
if (array.some((value: unknown): boolean => value !== value)
|| (inf && negInf)) { return NaN; }
if (inf) { return Infinity; }
if (negInf) { return -Infinity; }
/* sum hi */
let hi = array.filter((value: unknown): boolean =>
(value === 1e20 || value === -1e20))
.reduce((acc, value): number => acc + value, 0);
/* sum lo - Kahan sum */
let lo: number = 0.0;
let c: number = 0.0;
for (let item of array.filter((value: unknown): boolean =>
(value !== 1e20 && value !== -1e20))) {
let y = item - c; let t = lo + y; c = (t - lo) - y; lo = t;
}
/* return sum values */
/*
if (lo === 0 && hi !== 0) { return hi; }
if (lo > 0 && hi > 0) { return hi; }
if (lo < 0 && hi < 0) { return hi; }
if (lo > 0 && hi < 0) { return lo + hi; }
if (lo < 0 && hi > 0) { return lo + hi; }
if (lo === 0 && hi === 0) { return lo; }
if (lo !== 0 && hi === 0) { return lo; }
*/
if ((lo === 0 && hi !== 0) || (lo > 0 && hi > 0) || (lo < 0 && hi < 0)) {
return hi;
}
if ((lo > 0 && hi < 0) || (lo < 0 && hi > 0)) { return lo + hi; }
return lo;
}
/* not number items -> TypeError */
throw new TypeError("values passed to Math.sumPrecise must be numbers");
};
}
/* Error.isError(); */
if (!("isError" in Error)) {
// @ts-ignore
Error.isError = function isError (value: unknown) {
let className =
Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
return (className === "error" || className === "domexception");
};
}
/* Object.groupBy(); */
if (!("groupBy" in Object)) {
// @ts-ignore
Object.defineProperty(Object, "groupBy", {
"configurable": true, "writable": true, "enumerable": true,
"value": function (items: IterableAndIterator, callbackFn: Function) {
if (!(typeof callbackFn === "function")) { throw new TypeError(); }
let result = Object.create(null);
let index: number = 0;
for (let item of items as Iterable) {
let key = callbackFn(item, index++);
if (!(Object.prototype.hasOwnProperty.call(result, key))) {
result[key] = [];
}
result[key].push(item);
}
return result;
}
});
}
/* Map.groupBy(); */
if (!("groupBy" in Map)) {
Object.defineProperty(Map, "groupBy", {
"configurable": true, "writable": true, "enumerable": true,
"value": function (items: IterableAndIterator, callbackFn: Function) {
if (!(typeof callbackFn === "function")) { throw new TypeError(); }
let result = new Map();
let index: number = 0;
for (let item of items as Iterable) {
let key = callbackFn(item, index++);
if (!(result.has(key))) { result.set(key, []); }
result.get(key).push(item);
}
return result;
}
});
}
/* Array.fromAsync(); */
if (!Array.fromAsync) {
// @ts-ignore
Array.fromAsync = async function fromAsync (arrayLike, mapfn, thisArg) {
const isConstructor = (value: unknown): boolean =>
(typeof value === "function" && typeof value.prototype === "object");
const errorMsg = "Input length exceed the Number.MAX_SAFE_INTEGER.";
if (Symbol.asyncIterator in arrayLike || Symbol.iterator in arrayLike) {
let result: any[] = isConstructor(this) ? new this : Array(0);
let index: number = 0;
for await (const item of arrayLike) {
if (index > Number.MAX_SAFE_INTEGER) {
throw TypeError(errorMsg);
} else {
if (!mapfn) {
result[index] = item;
} else {
result[index] = await mapfn.call(thisArg,item,index);
}
}
index++;
}
result.length = index;
return result;
} else {
let length: number = arrayLike.length;
let result: any[] = isConstructor(this) ? new this(length) : Array(length);
let index: number = 0;
while (index < length) {
if (index > Number.MAX_SAFE_INTEGER) { throw TypeError(errorMsg); }
let item: any = await arrayLike[index];
if (!mapfn) {
result[index] = item;
} else {
result[index] = await mapfn.call(thisArg,item,index);
}
index++;
}
result.length = index;
return result;
}
};
}
/* crypto.randomUUID(); */
if (("crypto" in globalThis) && !("randomUUID" in globalThis.crypto)) {
// @ts-ignore
globalThis.crypto.randomUUID = function randomUUID () {
// @ts-ignore
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,
(c: any): any =>
(c^crypto.getRandomValues(new Uint8Array(1))[0]&15 >> c/4).toString(16)
);
};
}
/* Object.hasOwn(); */
if (!Object.hasOwn) {
Object.defineProperty(Object, "hasOwn", {
configurable: true, enumerable: false, writable: true,
value: function (object: object, property: string): boolean {
if (object == null) {
throw new TypeError("Cannot convert undefined or null to object");
}
return Object.prototype.hasOwnProperty.call(Object(object), property);
}
});
}
/* Array.prototype.toReversed(); */
if (!("toReversed" in Array.prototype)) {
Object.defineProperty(Array.prototype, "toReversed", {
"configurable": true, "writable": true, "enumerable": false,
"value": function () { return this.slice().reverse(); }
});
}
/* Array.prototype.toSorted(); */
if (!("toSorted" in Array.prototype)) {
Object.defineProperty(Array.prototype, "toSorted", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (fn: Function) { return this.slice().sort(fn); }
});
}
/* Array.prototype.toSpliced(); */
if (!("toSpliced" in Array.prototype)) {
Object.defineProperty(Array.prototype, "toSpliced", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (
start: number,
deleteCount: number,
...items: any[]): any[] {
let result: any[] = this.slice();
result.splice(start, deleteCount, ...items);
return result;
}
});
}
/* Array.prototype.with(); */
if (!("with" in Array.prototype)) {
Object.defineProperty(Array.prototype, "with", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (index: string | number, value: unknown): any[] {
let result = this.slice();
result[index] = value;
return result;
}
});
}
/* TypedArray.prototype.toReversed(); */
if (!("toReversed" in Uint8Array.prototype)) {
Object.defineProperty(Uint8Array.prototype, "toReversed", {
"configurable": true, "writable": true, "enumerable": false,
"value": function () {return this.slice().reverse();}
});
}
/* TypedArray.prototype.toSorted(); */
if (!("toSorted" in Uint8Array.prototype)) {
Object.defineProperty(Uint8Array.prototype, "toSorted", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (fn: Function) { return this.slice().sort(fn); }
});
}
/* TypedArray.prototype.with(); */
if (!("with" in Uint8Array.prototype)) {
Object.defineProperty(Uint8Array.prototype, "with", {
"configurable": true, "writable": true, "enumerable": false,
"value": function (index: string | number, value: unknown) {
let result = this.slice();
result[index] = value;
return result;
}
});
}
/* globalThis.GeneratorFunction; */
// @ts-ignore
if (!globalThis.GeneratorFunction) {
// @ts-ignore
globalThis.GeneratorFunction =
Object.getPrototypeOf(function*(){}).constructor;
}
/* globalThis.AsyncFunction; */
// @ts-ignore
if (!globalThis.AsyncFunction) {
// @ts-ignore
globalThis.AsyncFunction =
Object.getPrototypeOf(async function(){}).constructor;
}
/* globalThis.AsyncGeneratorFunction; */
// @ts-ignore
if (!globalThis.AsyncGeneratorFunction) {
// @ts-ignore
globalThis.AsyncGeneratorFunction =
Object.getPrototypeOf(async function* () {}).constructor;
}
/** Core API **/
/* Alphabet constans */
const BASE16 = "0123456789ABCDEF";
const BASE32 = "234567ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const WORDSAFEALPHABET = "23456789CFGHJMPQRVWXcfghjmpqvwx"; /* 31 */
/* assert(value: unknown [, message | error]): thrown error */
/**
* @description Ensures that `condition` is truthy. Throws an `Error` if falsy.
*
* @param {unknown} condition The value to check.
* @param {unknown} [message] - Optional message or Error to throw.
* @throws {Error} If assertion is failed.
*/
function assert (condition: unknown, message?: unknown): asserts condition {
if (!condition) {
// @ts-ignore
if (Error.isError(message)) { throw message; }
let errorMessage =
`[assert] Assertion failed: ${condition} should be truly${message ? " - " + message : ""}`;
throw new Error(errorMessage, {cause: errorMessage});
}
}
/* eq (value1: any, value2: any): boolean */
/**
* @description SameValueZero equality (like `Object.is`, but +0 === -0).
*
* @param {unknown} value1
* @param {unknown} value2
* @returns {boolean}
*/
const eq = (value1: unknown, value2: unknown): boolean =>
value1 === value2 || (value1 !== value1 && value2 !== value2);
/* gt (value1: any, value2: any): boolean */
/**
* @description Greater than.
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function gt (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2) && value1 > value2;
}
/* gte (value1: any, value2: any): boolean */
/**
* @description Greater than or equal (SameValueZero).
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function gte (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2)
&& (value1 > value2
|| value1 === value2
|| (value1 !== value1 && value2 !== value2));
}
/* lt (value1: any, value2: any): boolean */
/**
* @description Less than.
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function lt (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2) && value1 < value2;
}
/* lte (value1: any, value2: any): boolean */
/**
* @description Less than or equal (SameValueZero).
*
* @param {any} value1
* @param {any} value2
* @returns {boolean}
*/
function lte (value1: Comparable, value2: Comparable): boolean {
const _typeOf = (value: unknown): string =>
value === null ? "null" : typeof value;
return _typeOf(value1) === _typeOf(value2)
&& (value1 < value2
|| value1 === value2
|| (value1 !== value1 && value2 !== value2));
}
/* tap(function: function): function(v) */
function tap (fn: Function): any {
return function (value: unknown): any { fn(value); return value; };
}
/* once(function: function): function */
function once (fn: Function): Function {
let called: boolean = false;
let result: any;
return function (...args: any[]): any {
if (!called) {
called = true;
result = fn(...args);
}
return result;
};
}
/* curry (function: function): function */
function curry (fn: Function): Function {
const curried = (...args: any[]): any =>
args.length >= fn.length
? fn(...args)
: (...rest: any[]): any => curried(...args, ...rest);
return curried;
}
/* pipe (function1:function [, functionN: function]): function */
const pipe = (...functions: Function[]): Function =>
(first: any): any =>
functions.reduce((value: unknown, fn: Function): any => fn(value), first);
/* compose (function1: function [, functionN: function]): function */
const compose = (...functions: Function[]): Function =>
(first: any): any => functions.reduceRight((value, fn): any => fn(value), first);
/* pick (object: object, keys: array): object */
const pick = (obj: MapLike, keys: string[]): MapLike =>
keys.reduce(function (acc: MapLike, key: string) {
if (key in obj) { acc[key] = obj[key]; }
return acc;
}, {});
/* omit (object: object, keys: array): object */
const omit = (obj: MapLike, keys: string[]): MapLike =>
Object.keys(obj).reduce(function (acc: MapLike, key: string) {
// @ts-ignore
if (!keys.includes(key)) { acc[key] = obj[key]; }
return acc;
}, {});
/* assoc (object: object, key: string, value: unknown): object */
const assoc = (obj: MapLike, key: string, value: unknown): MapLike =>
({...obj, [key]: value});
/* asyncNoop (): Promise - do nothing */
// @ts-ignore
function asyncNoop (): Promise {
return new Promise(function (resolve: Function) { resolve(); });
}
/* asyncT (): Promise - return true */
async function asyncT (): Promise { return true; }
/* asyncF (): Promise - return false */
async function asyncF (): Promise { return false; }
/* asyncConstant (value): async function */
function asyncConstant (value: unknown): Function {
return async function() { return value; };
}
/* asyncIdentity (value): Promise - return value */
async function asyncIdentity (value: unknown): Promise { return value; }
/* deleteOwnProperty(object, property [,Throw = false]): number | thrown error*/
function deleteOwnProperty (
obj: Object,
property: string,
Throw: boolean = false): number {
if (Object.hasOwn(obj, property)) {
// @ts-ignore
delete obj[property];
let result = Object.hasOwn(obj, property);
if (result && Throw) { throw new Error("[deleteOwnProperty] error"); }
return +!result;
}
return -1;
}
/* createPolyfillMethod(object, property, function: any): boolean */
function createPolyfillMethod (
obj: Object,
property: string,
value: Function): boolean {
if (!(Object.hasOwn(obj, property))) {
Object.defineProperty(obj, property, {
writable: true, enumerable: false, configurable: true, value: value
});
}
// @ts-ignore
return (obj[property] === value);
}
/* createPolyfillProperty(object, property, value: unknown): boolean */
function createPolyfillProperty (
obj: object,
property: string,
value: unknown): boolean {
if (!(Object.hasOwn(obj, property))) {
Object.defineProperty(obj, property, {
writable: true, enumerable: true, configurable: true, value: value
});
}
// @ts-ignore
return (obj[property] === value);
}
/* randomUUIDv7(v4: boolean = false): string */
function randomUUIDv7 (v4: boolean = false): string {
let ts = Date.now().toString(16).padStart(12,"0") + (v4 ? "4" : "7");
// @ts-ignore
let uuid = Array.from(([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, (c): any =>
(c^crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
));
let index: number = 0;
let pos: number = 0;
while (index < 13) {
if (pos === 8 || pos === 13) { pos++; }
uuid[pos] = ts[index];
pos++;
index++;
}
return uuid.join("");
}
/* delay(ms: integer).then(callback: function): promise */
const delay = (milisec: number): Promise =>
new Promise(resolve => setTimeout(resolve, milisec));
/* randomBoolean(): boolean */
const randomBoolean = (): boolean => !Math.round(Math.random());
/* getUrlVars([str = location.search]): Object */
const getUrlVars = (str: string = location.search): Object =>
[...new URLSearchParams(str).entries()]
// @ts-ignore
.reduce(function (obj, item) { obj[item[0]] = item[1]; return obj; }, {});
/* obj2string(object): string */
const obj2string = (obj: object): string => Object.keys(obj).reduce(
(str, key: string): string => str
// @ts-ignore
+= encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]) + "&",
"").slice(0, -1);
/* extend([deep: boolean,] target: any, source1: any[, sourceN]): object*/
/**
* @description Deep assign of an object (Object, Array, etc.)
*
* @returns any
*/
function extend (target: T, source: U): T & U;
function extend (target: T, s1: U, s2: V): T & U & V;
function extend (deep: true, target: T, ...sources: any[]): T;
function extend (deep: false, target: T, ...sources: any[]): T;
function extend (target: object, ...sources: any[]): object;
function extend (...args: any[]): any {
/* Arguments checking */
let deep: boolean = false;
let target: any;
let i = 0;
if (args[0] === true) {
deep = true;
target = args[1] || {};
i = 2;
} else {
target = args[0] || {};
i = 1;
}
/* Helper functions */
const _isPlainObject = (obj: any): obj is Record =>
obj != null
&& typeof obj === "object"
&& (obj.constructor === Object || obj.constructor == null);
const _isDate = (value: any): value is Date => value instanceof Date;
const _isRegExp = (value: any): value is RegExp => value instanceof RegExp;
const _isMap = (value: any): value is Map => value instanceof Map;
const _isSet = (value: any): value is Set => value instanceof Set;
/* */
function merge(target: any, source: any): any {
/* Identical or non-object -> direct assign */
if (Object.is(source, target) || source == null || typeof source !== "object") {
return source;
}
/* Date -> clone */
if (_isDate(source)) { return new Date(source.getTime()); }
/* RegExp -> clone */
if (_isRegExp(source)) { return new RegExp(source); }
/* Map -> deep merge entries */
if (_isMap(source)) {
if (!_isMap(target)) { target = new Map(); }
for (let [key, value] of source) {
const tv = target.get(key);
target.set(key, deep ? merge(tv, value) : value);
}
return target;
}
/* Set -> deep union */
if (_isSet(source)) {
if (!_isSet(target)) { target = new Set(); }
for (let item of source) {
if (deep) {
if (target.has(item)) { continue; }
}
target.add(item);
}
return target;
}
/* Array -> deep merge by index */
if (Array.isArray(source)) {
if (!Array.isArray(target)) { target = []; }
const srcLength = source.length;
for (let i = 0; i < srcLength; i++) {
let sv = source[i];
let tv = target[i];
target[i] = deep ? merge(tv, sv) : sv;
}
return target;
}
/* Plain object -> deep merge keys */
if (_isPlainObject(source)) {
if (!_isPlainObject(target)) { target = {}; }
for (let key in source) {
let sv = source[key];
let tv = target[key];
target[key] = deep ? merge(tv, sv) : sv;
}
return target;
}
/* Fallback: copy by reference */
return source;
}
/* Clone all sources */
const length = args.length;
for (; i < length; i++) { merge(target, args[i]); }
return target;
}
/* sizeIn(object): integer */
const sizeIn = (obj: object): number =>
Object.getOwnPropertyNames(obj).length
+ Object.getOwnPropertySymbols(obj).length;
/* unBind(function): function */
const unBind = (fn: Function): Function => Function.prototype.call.bind(fn);
/* bind(function, context: any): function */
/** @return {Function} */
const bind = Function.prototype.call.bind(Function.prototype.bind);
/* constant(value: unknown): unknown */
/**
* @description Returns a function that always returns the same value.
*
* @param {unknown} value
* @returns {unknown}
*/
const constant = (value: T): (() => T) => () => value;
/* identity(value: unknown): any */
/**
* @description Returns value unchanged.
*
* @param {unknown} value
* @returns {unknown}
*/
const identity = (value: T): T => value;
/* noop(): undefined */
/**
* @description A function that does nothing.
*
* @returns {void}
*/
function noop (): void {}
/* T(): true */
/**
* @description Always returns true.
*
* @returns {true}
*/
const T = (): boolean => true;
/* F(): false */
/**
* @description Always returns false.
*
* @returns {false}
*/
const F = (): boolean => false;
/* nanoid([size = 21 [,
alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"]])
: string */
function nanoid (
size = 21,
alphabet: string =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
): string {
let result: string = "";
let dl: number = alphabet.length;
let pos: number;
let index: number = size;
while (index--) {
do { pos = crypto.getRandomValues(new Uint8Array(1))[0]; } while
(pos >= dl);
result += alphabet[pos];
}
return result;
}
/* timestampID([size = 21
[, alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"]])
: string */
function timestampID (
size: number = 21,
alphabet: string =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
): string {
let result: string = Date.now().toString(36).padStart(10, "0") + "-";
let dl: number = alphabet.length;
let pos: number;
let index: number = ((size > 11) ? size : 12) - 11;
while (index--) {
do { pos = crypto.getRandomValues(new Uint8Array(1))[0]; } while
(pos >= dl);
result += alphabet[pos];
}
return result;
}
/** String API **/
/* b64Encode(s: any): string */
function b64Encode (str: any): string {
return btoa(encodeURIComponent(String(str)).replace(/%([0-9A-F]{2})/g,
function toSolidBytes (_match, p1): string {
// @ts-ignore
return String.fromCharCode("0x" + p1);
}
));
}
/* b64Decode(s: string): string */
function b64Decode (str: any): string {
return decodeURIComponent(atob(String(str)).split("").map(function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
}).join(""));
}
/* strTruncate(string: string, newLength: integer [, omission: string = ""]):
string */
function strTruncate (
str: any,
newLength: number,
omission: string = ""): string {
str = String(str);
omission = String(omission);
let strUC = Array.from(str);
if (newLength >= strUC.length) { return str; }
return strUC.slice(0, newLength-Array.from(omission).length).join("")
+ omission;
}
/* strPropercase(s: any): string */
const strPropercase = (str: any): string =>
String(str).trim().split(" ").map(function (value: string) {
let chars = Array.from(value).map( (c: string): string => c.toLowerCase() );
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}).join(" ");
/* strTitlecase(s: any): string */
const strTitlecase = (str: any): string =>
String(str).trim().split(" ").map(function (value: string) {
let chars = Array.from(value).map( (c: string): string => c.toLowerCase() );
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}).join(" ");
/* strCapitalize(s: any): string */
function strCapitalize (str: any): string {
let chars = [...String(str).trim().toLowerCase()];
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}
/* strUpFirst(s: any): string */
function strUpFirst (str: any): string {
let chars = [...String(str).trim()];
if (chars.length) { chars[0] = chars[0].toUpperCase(); }
return chars.join("");
}
/* strDownFirst(s: any): string */
function strDownFirst (str: any): string {
let chars = [...String(str).trim()];
if (chars.length) { chars[0] = chars[0].toLowerCase(); }
return chars.join("");
}
/* strReverse(s: any): string */
const strReverse = (str: any): string =>
Array.from(String(str)).reverse().join("");
/* strCodePoints(s: any): array of strings */
const strCodePoints = (str: any): any[] =>
Array.from(String(str), (value: string): number | undefined =>
value.codePointAt(0));
/* strFromCodePoints(iterator: iterator): string */
const strFromCodePoints = ([...array]): string =>
String.fromCodePoint(...array);
/* strAt(string: string, index: number [, newChar: string]): string */
function strAt (str: string, index: number, newChar?: string): string {
let chars: string[] = Array.from(String(str));
if (newChar == null) { return chars.at(index) || ""; }
index = index < 0 ? chars.length + index : index;
if (index > chars.length) { return chars.join(""); }
chars[index] = newChar;
return chars.join("");
}
/* strSplice(string: string, index: number, count: integer [, add: string]):
string */
const strSplice = (str: string, index: number,count: number, ...add: any[]): string =>
Array.from(str).toSpliced(index, count, add.join("")).join("");
/* strHTMLRemoveTags(s: any): string */
const strHTMLRemoveTags = (str: any): string =>
String(str).trim().replace(/<[^>]*>/g, " ").replace(/\s{2,}/g, " ").trim();
/* strHTMLEscape(str: any): string */
const strHTMLEscape = (str: any): string =>
String(str).trim()
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
/* strHTMLUnEscape(s: any): string */
const strHTMLUnEscape = (str: string): string =>
String(str).trim()
.replace(/&/g, "&").replace(/&/g, "&")
.replace(/</g, "<").replace(/</g, "<")
.replace(/>/g, ">").replace(/>/g, ">")
.replace(/"/g, '"').replace(/"/g, '"')
.replace(/'/g, "'").replace(/'/g, "'");
/** DOM API **/
/* qsa(selector: string [, context: element object]): array */
const qsa = (str: string, context: Document | HTMLElement = document): any[] =>
Array.from(context.querySelectorAll(str));
/* qs(selector: string [, context: element object]): element object | null */
const qs = (str: string, context: Document | Element = document): HTMLElement | null =>
context.querySelector(str);
/* domReady(callback: function): undefined */
function domReady (fn: Function): void {
if (document.readyState !== "loading") {
fn();
} else {
document.addEventListener("DOMContentLoaded", function (_event) { fn(); });
}
}
/* domCreate(type: string[, properties: object[, innerHTML: string]]):
element */
/* domCreate(element descriptive object): element */
function domCreate (
elementType: string | MapLike,
properties: object,
innerHTML: string): HTMLElement {
if (arguments.length === 1 && typeof elementType === "object") {
let obj = elementType;
elementType = obj.elementType;
properties = {};
for (let key in obj) {
// @ts-ignore
if (key !== "elementType") { properties[key] = obj[key]; }
}
}
let element: HTMLElement = document.createElement(elementType as string);
if (properties) {
for (let key in properties) {
// @ts-ignore
if (key !== "style" || typeof properties[key] === "string") {
// @ts-ignore
element[key] = properties[key];
} else {
// @ts-ignore
Object.assign(element.style, properties[key]);
}
}
}
if (innerHTML) { element.innerHTML = innerHTML; }
return element;
}
/* domToElement(htmlString): element object */
function domToElement (str: string): Element | null {
let element: HTMLElement = document.createElement("div");
element.innerHTML = str;
return element.firstElementChild;
}
/* domGetCSS(element [, property: string]): string */
const domGetCSS = (element: Element, property: string | number): string | CSSStyleDeclaration =>
// @ts-ignore
(property ? globalThis.getComputedStyle(element, null)[property] :
globalThis.getComputedStyle(element, null));
/* domSetCSS(element, property: string, value: string): undefined */
/* domSetCSS(element, properties: object): undefined */
function domSetCSS (
element: HTMLElement,
property: string | object,
value: string): void {
if (typeof property === "string") {
// @ts-ignore
element.style[property] = value;
} else if (typeof property === "object") {
Object.keys(property).forEach((key: string): void =>
// @ts-ignore
element.style[key] = property[key]
);
}
}
/* domFadeIn(element [, duration = 500 [, display = ""]]): undefined */
function domFadeIn (
element: HTMLElement,
duration: number,
display: string): void {
let s = element.style;
let step: number = 25/(duration || 500);
s.opacity = (s.opacity ?? 0);
s.display = (display || "");
(function fade () {
// @ts-ignore
(s.opacity=parseFloat(s.opacity)+step)>1 ? s.opacity=1 :setTimeout(fade,25);
})();
}
/* domFadeOut(element [, duration = 500]): undefined */
function domFadeOut (
element: HTMLElement, duration: number): void {
let style = element.style;
let step: number = 25/(duration || 500);
// @ts-ignore
style.opacity = (style.opacity || 1);
(function fade () {
// @ts-ignore
(style.opacity -= step) < 0 ? style.display = "none" : setTimeout(fade, 25);
})();
}
/* domFadeToggle(element [, duration = 500 [, display = ""]]): undefined */
function domFadeToggle (
element: HTMLElement, duration: number, display: string = ""): void {
if (globalThis.getComputedStyle(element, null).display === "none") {
/* same as domFadeIn(); */
let style = element.style;
let step: number = 25/(duration || 500);
style.opacity = (style.opacity ?? 0);
style.display = (display || "");
(function fade () {
// @ts-ignore
(style.opacity = parseFloat(style.opacity) + step) > 1 ? style.opacity = 1 :
setTimeout(fade, 25);
})();
} else {
/* same as domFadeOut(); */
let style = element.style;
let step: number = 25/(duration || 500);
style.opacity = (style.opacity ?? 1);
(function fade () {
// @ts-ignore
(style.opacity -= step) < 0 ? style.display = "none" : setTimeout(fade, 25);
})();
}
}
/* domHide(element): undefined */
const domHide = (element: HTMLElement): any => element.style.display = "none";
/* domShow(element [, display = ""]): undefined */
const domShow = (element: HTMLElement, display: string = ""): any =>
element.style.display = display;
/* domToggle(element [, display: string]): undefined */
function domToggle (element: HTMLElement, display: string = ""): void {
if (globalThis.getComputedStyle(element, null).display === "none") {
element.style.display = display;
} else {
element.style.display = "none";
}
}
/* domIsHidden(element): boolean */
const domIsHidden = (element: Element): boolean =>
(globalThis.getComputedStyle(element,null).display === "none");
/* domSiblings(element): array */
const domSiblings = (element: Element): Element[] =>
// @ts-ignore
Array.prototype.filter.call(element.parentNode.children,
(item: Element): boolean => (item !== element)
);
/* domSiblingsPrev(element): any[] */
const domSiblingsPrev = (element: Element): Element[] =>
Array.prototype.slice.call(
// @ts-ignore
element.parentNode.children,
0,
// @ts-ignore
Array.prototype.indexOf.call(element.parentNode.children, element)
);
/* domSiblingsLeft(element): any[] */
const domSiblingsLeft = (element: Element): Element[] =>
Array.prototype.slice.call(
// @ts-ignore
element.parentNode.children,
0,
// @ts-ignore
Array.prototype.indexOf.call(element.parentNode.children, element)
);
/* domSiblingsNext(element): any[] */
const domSiblingsNext = (element: Element): Element[] =>
Array.prototype.slice.call(
// @ts-ignore
element.parentNode.children,
// @ts-ignore
Array.prototype.indexOf.call(element.parentNode.children, element) + 1,
// @ts-ignore
element.parentNode.children.length
);
/* domSiblingsRight(element): any[] */
const domSiblingsRight = (element: HTMLElement): Element[] =>
Array.prototype.slice.call(
// @ts-ignore
element.parentNode.children,
// @ts-ignore
Array.prototype.indexOf.call(element.parentNode.children, element) + 1,
// @ts-ignore
element.parentNode.children.length
);
/* importScript(script1: string [, scriptN: string]): undefined */
function importScript (...scripts: string[]): void {
for (let item of scripts) {
let element: HTMLScriptElement = document.createElement("script");
element.type = "text\/javascript";
element.src = item;
// @ts-ignore
element.onerror = function (error: Error): void {
throw new URIError(
// @ts-ignore
"Loading failed for the script with source " + error.target.src
);
};
(document.head||document.getElementsByTagName("head")[0]).appendChild(element);
}
}
/* importStyle(style1: string [, styleN: string]): undefined */
function importStyle (...styles: string[]): void {
for (let item of styles) {
let element: HTMLLinkElement = document.createElement("link");
element.rel = "stylesheet";
element.type = "text\/css";
element.href = item;
element.onerror = function (error) {
throw new URIError(
// @ts-ignore
"Loading failed for the style with source " + error.target.href
);
};
(document.head ||document.getElementsByTagName("head")[0]).appendChild(element);
}
}
/* form2array(form): object[] */
function form2array (form: HTMLFormElement): object[] {
let field: any;
let result = Array