You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

728 lines
20 KiB

1 year ago
class Tools {
/**
* undefined
* @param obj
* @returns undefined
*/
public static isUndefined(obj: any): boolean {
return typeof obj === 'undefined';
}
/**
* null undefined
* @param obj
* @returns null undefined
*/
public static isUndefinedOrNull(obj: any): boolean {
return obj === null || typeof obj === 'undefined';
}
/**
* null undefined
* @param obj
* @returns null undefined
*/
public static isEmpty(obj: any): boolean {
return obj == null || typeof obj == 'undefined' || obj == '';
}
/**
*
* @param obj
* @returns
*/
public static isObject(obj: any): boolean {
return !Tools.isEmpty(obj) && typeof obj === 'object';
}
/**
*
* @param obj
* @returns
*/
public static isArray(obj: any): boolean {
return !Tools.isEmpty(obj) && Array.isArray(obj);
}
/**
*
* @param date
* @returns
*/
public static isCurrentDay(date: Date): boolean {
return new Date().toISOString().slice(0, 10) === date.toISOString().slice(0, 10);
}
/**
*
* @param min
* @param max
* @param date
* @returns
*/
public static isBetweenTwoDates(min: Date, max: Date, date: Date): boolean {
return date.getTime() >= min.getTime() && date.getTime() <= max.getTime();
}
/**
*
* @param date
* @returns
*/
public static isWeekend(date: Date): boolean {
return date.getDay() === 6 || date.getDay() === 0;
}
/**
*
* @param date
* @param year
* @returns
*/
public static isInAYear(date: Date, year: number): boolean {
return date.getUTCFullYear() === new Date(`${year}`).getUTCFullYear();
}
/**
* 24 am. pm.
* @param h
* @returns
*/
public static toAMPMFormat(h: number): string {
return `${h % 12 === 0 ? 12 : h % 12}${h < 12 ? ' am.' : ' pm.'}`;
}
/**
*
* @param param0
* @returns
*/
public static capitalize([first, ...rest]: any): string {
return `${first.toUpperCase()}${rest.join('')}`;
}
/**
*
* @param param0
* @returns
*/
public static lowercaseFirst([first, ...rest]: any): string {
return `${first.toLowerCase()}${rest.join('')}`;
}
/**
* emoji
* @param c
* @returns emoji
*/
public static letterToEmoji(c: string): string {
return String.fromCodePoint(c.toLowerCase().charCodeAt(0) + 127365);
}
/**
*
* @param str
* @returns
*/
public static isPalindrome(str: string): boolean {
return str.toLowerCase() === str.toLowerCase().split('').reverse().join('');
}
/**
*
* @param n
* @returns
*/
public static getFactorial(n: number): number {
return n <= 1 ? 1 : n * Tools.getFactorial(n - 1);
}
/**
* N
* @param n N
* @param memo
* @returns
*/
public static getFibonacci(n: number, memo: number[]): number {
return memo[n] || (n <= 2 ? 1 : (memo[n] = Tools.getFibonacci(n - 1, memo) + Tools.getFibonacci(n - 2, memo)));
}
/**
*
* @param arr
* @returns
*/
public static copyToArray(arr: any[]): any[] {
return [...arr];
}
/**
*
* @param arr
* @returns
*/
public static getUnique(arr: any[]): any[] {
return [...new Set(arr)];
}
/**
*
* @param arr
* @returns
*/
public static shuffle(arr: number[]): number[] {
return arr.sort(() => Math.random() - 0.5);
}
/**
*
* @param str
* @returns
*/
public static reverseString(str: string): string {
return str.split('').reverse().join('');
}
/**
*
* @param arr1
* @param arr2
* @returns
*/
public static containSameValues(arr1: any[], arr2: any[]): boolean {
return arr1.sort().join(',') === arr2.sort().join(',');
}
/**
* (->)
* = 32 + × 1.8
* @param celsius
* @returns
*/
public static toFahrenheit(celsius: number): number {
return (celsius * 9) / 5 + 32;
}
/**
* (->)
* = 32 + × 1.8
* @param fahrenheit
* @returns
*/
public static toCelsius(fahrenheit: number): number {
return ((fahrenheit - 32) * 5) / 9;
}
/**
* cookie
* @returns void
*/
public static clearAllCookies(): void {
document.cookie.split(';').forEach((c) => (document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)));
}
/**
*
* @param f
* @returns
*/
public static isAsyncFunction(f: any): boolean {
return Object.prototype.toString.call(f) === '[object AsyncFunction]';
}
/**
*
* @returns
*/
public static runningInBrowser(): boolean {
return typeof window === 'object' && typeof document === 'object';
}
/**
* Node
* @returns Node
*/
public static runningInNode(): boolean {
return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
}
/**
*
* @returns
*/
public static isDarkMode(): boolean {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
/**
* dom
* @param element dom
* @returns void
*/
public static toTop(element: HTMLElement): void {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
/**
* dom
* @param element dom
* @returns void
*/
public static toBottom(element: HTMLElement): void {
element.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
/**
* JSON MAP
* @param json json
* @returns MAP
*/
public static jsonToMap(json: string): Map<any, any> {
return new Map(Object.entries(JSON.parse(json)));
}
/**
* json
* @param obj
* @returns json
*/
public static object2Json(obj: any): string | null {
return Tools.isEmpty(obj) ? null : JSON.stringify(obj);
}
/**
* json
* @param json json
* @returns
*/
public static json2Object(json: string): any {
return Tools.isEmpty(json) ? null : JSON.parse(json);
}
/**
*
* 使:
* const array =['001','002','003'];
* const joined =join(array); // joined='001-002-003'
*
* const objArray =[{name:'001',age:10},{name:'002',age:20}];
* const joined =join(array,'-','name'); // joined='001-002'
* @param array
* @param joiner
* @param propertyName , , js js null
* @returns
*/
public static join(array: any, joiner: string, propertyName?: string): string {
if (Tools.isEmpty(array)) {
return '';
}
propertyName = propertyName || '';
if (Array.isArray(array)) {
let result = '';
if (array.length > 0) {
for (let i = 0; i < array.length; i++) {
if (propertyName == '') {
result += array[i] + joiner;
} else {
result += array[i][propertyName] + joiner;
}
}
}
if (result != '') {
result = result.substring(0, result.length - 1);
}
return result;
} else {
return array;
}
}
/**
*
* @param target
* @returns
*/
public static deepClone(target: any): any {
const map = new WeakMap();
function isObject(target: any) {
return (typeof target === 'object' && target) || typeof target === 'function';
}
function clone(data: any) {
if (!isObject(data)) {
return data;
}
if ([Date, RegExp].includes(data.constructor)) {
return new data.constructor(data);
}
if (typeof data === 'function') {
return new Function('return ' + data.toString())();
}
const exist = map.get(data);
if (exist) {
return exist;
}
if (data instanceof Map) {
const result = new Map();
map.set(data, result);
data.forEach((val, key) => {
if (isObject(val)) {
result.set(key, clone(val));
} else {
result.set(key, val);
}
});
return result;
}
if (data instanceof Set) {
const result = new Set();
map.set(data, result);
data.forEach((val) => {
if (isObject(val)) {
result.add(clone(val));
} else {
result.add(val);
}
});
return result;
}
const keys = Reflect.ownKeys(data);
const allDesc = Object.getOwnPropertyDescriptors(data);
const result = Object.create(Object.getPrototypeOf(data), allDesc);
map.set(data, result);
keys.forEach((key) => {
const val = data[key];
if (isObject(val)) {
result[key] = clone(val);
} else {
result[key] = val;
}
});
return result;
}
return clone(target);
}
/**
* Http Get url
* 使:
* 1.
* const params =[
* {key:'name',value:'姓名'},
* {key:'年龄',value:20}
* ];
* const url =buildHttpQueryString(params); //url ='name=%E5%A7%93%E5%90%8D&%E5%B9%B4%E9%BE%84=20'
* 2.
* const params ={
* name:'姓名',
* 年龄:20
* };
* const url =buildHttpQueryString(params); //url ='name=%E5%A7%93%E5%90%8D&%E5%B9%B4%E9%BE%84=20'
* 3.
* const params ={
* name:'姓名',
* phone:[
* '13012345678',
* '13812345678'
* ]
* };
* const url =buildHttpQueryString(params); //url ='name=%E5%A7%93%E5%90%8D&phone=13012345678,13812345678'
* @param parameters
* @param encode
* @returns url
*/
public static buildHttpQueryString(parameters: any, encode?: true): string | null {
if (Tools.isEmpty(parameters)) return null;
const _parameters: any[] = [];
if (Tools.isArray(parameters)) {
//支持以 [{key:'name',value:'姓名'},{key:'age',value:20}] 形式的参数
for (let i = 0; i < parameters.length; i++) {
if (encode) {
_parameters[i] = encodeURIComponent(parameters[i].key) + '=' + encodeURIComponent(parameters[i].value);
} else {
_parameters[i] = parameters[i].key + '=' + parameters[i].value;
}
}
return Tools.join(_parameters, '&');
} else if (Tools.isObject(parameters)) {
//支持以 {name:'姓名',age:20} 形式的参数
let i = 0;
for (const key in parameters) {
const value = parameters[key];
if (Tools.isArray(value)) {
//支持以 {address:['上海','beijing']} 形式的参数
for (let j = 0; j < value.length; j++) {
if (encode) {
value[j] = encodeURIComponent(value[j]);
}
}
if (encode) {
_parameters[i++] = encodeURIComponent(key) + '=' + Tools.join(value, ',');
} else {
_parameters[i++] = key + '=' + Tools.join(value, ',');
}
} else {
if (encode) {
_parameters[i++] = encodeURIComponent(key) + '=' + encodeURIComponent(parameters[key]);
} else {
_parameters[i++] = key + '=' + parameters[key];
}
}
}
return Tools.join(_parameters, '&');
} else {
return null;
}
}
/**
* URL URL
* @param url1 URL
* @param url2 URL
*/
public static concatUrl(url1: string | null, url2: string | null): string {
return (Tools.removeUrlSuffixSlash(url1) || '') + '/' + (Tools.removeUrlPrefixSlash(url2) || '');
}
/**
* URL /
* @param url url
* @returns URL
*/
public static removeUrlPrefixSlash(url: string | null): string | null {
if (url) {
let _url = url;
while (_url.startsWith('/')) {
_url = _url.substring(1);
}
return _url;
}
return null;
}
/**
* URL /
* @param url url
* @returns URL
*/
public static removeUrlSuffixSlash(url: string | null): string | null {
if (url) {
let _url = url;
while (_url.endsWith('/')) {
_url = _url.substring(0, _url.length - 1);
}
return _url;
}
return null;
}
/**
* dom class
* @param target dom
* @param className class
*/
public static addClassName(target: HTMLElement | null, className: string | null): void {
if (target && className) {
const _class = target.getAttribute('class');
if (_class) {
const classes = _class.split(' ');
classes.push(className);
const clazzSet = [...new Set(classes)];
target.setAttribute('class', clazzSet.join(' '));
} else {
target.setAttribute('class', className);
}
}
}
/**
* dom class
* @param target dom
* @param className class
*/
public static removeClassName(target: HTMLElement | null, className: string | null): void {
if (target && className) {
const _class = target.getAttribute('class');
if (_class) {
let classes = _class.split(' ');
classes = [...new Set(classes)];
classes = classes.filter((item) => item !== className);
target.setAttribute('class', classes.join(' '));
}
}
}
/**
* javascript url
* @returns javascript url
*/
public static getJavascriptElementUrls(): string[] {
const result: string[] = [];
const scripts = document.getElementsByTagName('script');
for (const script of scripts) {
const url = script.getAttribute('src');
if (url) {
result.push(url);
}
}
return result;
}
/**
* dom <script src="..."></script>
* @param src javascript url
* @param target dom , dom head
* @param callback
*/
public static appendJavascriptTag(src: string | null, target?: HTMLElement, callback?: any): void {
if (src) {
const script = document.createElement('script') as HTMLScriptElement;
script.type = 'text/javascript';
script.src = src;
if (callback) {
script.onload = callback;
}
if (target) {
target.appendChild(script);
} else {
document.head.appendChild(script);
}
}
}
/**
* URL, iframe, iframe ,
* @param url URL
*/
public static download(url: string | null): void {
if (url) {
const iframeId = '_download_iframe';
let iframe = document.getElementById(iframeId) as HTMLIFrameElement;
if (iframe) {
iframe.src = url;
} else {
iframe = document.createElement('iframe');
iframe.id = iframeId;
iframe.src = url;
iframe.style.display = 'none';
document.getElementsByTagName('body')[0].appendChild(iframe);
}
}
}
/**
*
* @param title
*/
public static setTitile(title: string | null): void {
if (title) {
document.title = title;
}
}
/**
* icon
* @param iconUrl icon url
*/
public static setFavicon(favicon: string | null): void {
if (favicon) {
let faviconElement: HTMLLinkElement = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
if (faviconElement) {
console.log(faviconElement.href);
faviconElement.href = favicon;
} else {
faviconElement = document.createElement('link');
faviconElement.rel = 'shortcut icon';
faviconElement.href = favicon;
document.getElementsByTagName('head')[0].appendChild(faviconElement);
}
}
}
/**
* dom
* @param element dom dom ID
*/
public static removeDomElement(element: HTMLElement | string): void {
if (element) {
if (Tools.isObject(element)) {
(element as HTMLElement).parentNode?.removeChild(element as HTMLElement);
} else {
const e = document.getElementById(element as string);
if (e) {
e.parentNode?.removeChild(e);
}
}
}
}
/**
*
* @param value
* @param min
* @param max
* @returns
*/
public static range(value: number, min: number, max: number): number {
if (value < min) {
return min;
} else if (value > max) {
return max;
} else {
return value;
}
}
/**
*
* @param target
* @param source
*/
public static mergeObject(target: object, source: object): object {
if (source && target) {
for (const property in source) {
const value = source[property];
if (Tools.isObject(value) && !Tools.isArray(value)) {
//正常对象,排除 undefined 和 null
if (Tools.isUndefinedOrNull(target[property])) {
target[property] = {};
}
Tools.mergeObject(target[property], value);
} else {
if (!Tools.isUndefinedOrNull(value)) {
target[property] = value;
}
}
}
}
return target;
}
public static objectValueEquals(o1: object | null | undefined, o2: object | null | undefined): boolean {
if (Tools.isUndefinedOrNull(o1) && Tools.isUndefinedOrNull(o2)) {
return true;
}
if ((!Tools.isUndefinedOrNull(o1) && Tools.isUndefinedOrNull(o2)) || (Tools.isUndefinedOrNull(o1) && !Tools.isUndefinedOrNull(o2))) {
return false;
}
if (o1 === o2) {
return true;
}
for (const p1 in o1) {
if (o1[p1] != o2[p1]) {
return false;
}
}
for (const p2 in o2) {
if (o1[p2] != o2[p2]) {
return false;
}
}
return true;
}
}
export { Tools };