mazey 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -12
- package/{src/example.html → examples/index.html} +0 -0
- package/examples/index.ts +32 -0
- package/index.js +44 -0
- package/lib/index.cjs.js +1 -1
- package/lib/index.d.ts +229 -116
- package/lib/index.d.ts.map +1 -1
- package/lib/index.esm.js +1 -1
- package/lib/mazey.min.js +1 -1
- package/package.json +5 -4
- package/src/index.ts +344 -133
- package/webpack.config.dev.js +39 -0
- package/src/example.ts +0 -49
package/src/index.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* @description Computes the longest common substring of two strings.
|
|
6
6
|
* @param {string} aStr String
|
|
7
7
|
* @param {string} bStr String
|
|
8
|
-
* @
|
|
8
|
+
* @returns {number} Length
|
|
9
9
|
*/
|
|
10
|
-
export function calLongestCommonSubstring(aStr
|
|
10
|
+
export function calLongestCommonSubstring(aStr: string, bStr: string): number {
|
|
11
11
|
const aLen = aStr.length;
|
|
12
12
|
const bLen = bStr.length;
|
|
13
13
|
// 创建二维数组并且深拷贝
|
|
@@ -35,9 +35,9 @@ export function calLongestCommonSubstring(aStr = '', bStr = ''): number {
|
|
|
35
35
|
* @description 计算两个字符串的最长公共子序列
|
|
36
36
|
* @param {string} aStr 字符串
|
|
37
37
|
* @param {string} bStr 字符串
|
|
38
|
-
* @
|
|
38
|
+
* @returns {number} 长度
|
|
39
39
|
*/
|
|
40
|
-
export function calLongestCommonSubsequence(aStr
|
|
40
|
+
export function calLongestCommonSubsequence(aStr: string, bStr: string): number {
|
|
41
41
|
const aLen = aStr.length;
|
|
42
42
|
const bLen = bStr.length;
|
|
43
43
|
// 创建二维数组并且深拷贝
|
|
@@ -73,13 +73,14 @@ export function calLongestCommonSubsequence(aStr = '', bStr = ''): number {
|
|
|
73
73
|
* @method getQueryParam
|
|
74
74
|
* @description Get the query param's value of the current Web URL(`location.search`).
|
|
75
75
|
* @param {string} param Query param.
|
|
76
|
-
* @
|
|
77
|
-
|
|
78
|
-
export function getQueryParam(param
|
|
76
|
+
* @returns {string} value
|
|
77
|
+
*/
|
|
78
|
+
export function getQueryParam(param: string): string {
|
|
79
79
|
const reg = new RegExp('(^|&)' + param + '=([^&]*)(&|$)');
|
|
80
80
|
const r = location.search.substr(1).match(reg);
|
|
81
81
|
if (r !== null) {
|
|
82
|
-
return decodeURIComponent(unescape(r[2]));
|
|
82
|
+
// return decodeURIComponent(unescape(r[2]));
|
|
83
|
+
return decodeURIComponent(r[2]);
|
|
83
84
|
}
|
|
84
85
|
return '';
|
|
85
86
|
}
|
|
@@ -89,10 +90,12 @@ export function getQueryParam(param = ''): string {
|
|
|
89
90
|
* @description Get the query param's value of the input URL.
|
|
90
91
|
* @param {string} url URL string.
|
|
91
92
|
* @param {string} param Query param.
|
|
92
|
-
* @
|
|
93
|
-
|
|
94
|
-
export function getUrlParam(url
|
|
95
|
-
const result:
|
|
93
|
+
* @returns {string} value
|
|
94
|
+
*/
|
|
95
|
+
export function getUrlParam(url: string, param: string): string | string[] {
|
|
96
|
+
const result: {
|
|
97
|
+
[key: string]: string | string[] | any;
|
|
98
|
+
} = {};
|
|
96
99
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
|
|
97
100
|
url.replace(/\??(\w+)=([^&]*)&?/g, function (a, k, v): any {
|
|
98
101
|
if (result[k] !== undefined) {
|
|
@@ -116,9 +119,9 @@ export function getUrlParam(url = '', param = ''): string {
|
|
|
116
119
|
* @param {string} url URL string.
|
|
117
120
|
* @param {string} param Query param.
|
|
118
121
|
* @param {string} value Param's value.
|
|
119
|
-
* @
|
|
120
|
-
|
|
121
|
-
export function updateQueryParam(url
|
|
122
|
+
* @returns {string} URL.
|
|
123
|
+
*/
|
|
124
|
+
export function updateQueryParam(url: string, param: string, value: string): string {
|
|
122
125
|
const re = new RegExp('([?&])' + param + '=.*?(&|$)', 'i');
|
|
123
126
|
const separator = url.indexOf('?') !== -1 ? '&' : '?';
|
|
124
127
|
if (url.match(re)) {
|
|
@@ -132,9 +135,9 @@ export function getUrlParam(url = '', param = ''): string {
|
|
|
132
135
|
* @method getHashQueryParam
|
|
133
136
|
* @description Get the hash query param's value of the current Web URL(`location.hash`).
|
|
134
137
|
* @param {string} param Query param.
|
|
135
|
-
* @
|
|
138
|
+
* @returns {string} value
|
|
136
139
|
*/
|
|
137
|
-
export function getHashQueryParam(param
|
|
140
|
+
export function getHashQueryParam(param: string): string {
|
|
138
141
|
const hashs = location.hash.split('?');
|
|
139
142
|
if (hashs.length === 1) {
|
|
140
143
|
return '';
|
|
@@ -149,8 +152,8 @@ export function getHashQueryParam(param = ''): string {
|
|
|
149
152
|
* @description Get the domain of URL, and other params.
|
|
150
153
|
* @param {string} url
|
|
151
154
|
* @param {array} rules Object.keys(location), ['href', 'protocol', 'host', 'hostname', 'port', 'pathname', 'search', 'hash'], ['hostname', 'pathname'] = 'km.mazey.net/plugins/servlet/mobile'
|
|
152
|
-
|
|
153
|
-
export function getDomain(url
|
|
155
|
+
*/
|
|
156
|
+
export function getDomain(url: string, rules = ['hostname']): string {
|
|
154
157
|
const aEl: any = document.createElement('a');
|
|
155
158
|
aEl.href = url;
|
|
156
159
|
return rules.reduce((ret, v) => {
|
|
@@ -163,9 +166,9 @@ export function getDomain(url = '', rules = ['hostname']): string {
|
|
|
163
166
|
* @method camelCaseToKebabCase
|
|
164
167
|
* @description Transfer CamelCase to KebabCase.
|
|
165
168
|
* @param {string} camelCase 'aBC' or 'ABC'
|
|
166
|
-
* @
|
|
167
|
-
|
|
168
|
-
export function camelCaseToKebabCase(camelCase
|
|
169
|
+
* @returns {string} 'a-b-c'
|
|
170
|
+
*/
|
|
171
|
+
export function camelCaseToKebabCase(camelCase: string): string {
|
|
169
172
|
const kebabCase = camelCase.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
170
173
|
return kebabCase[0] === '-' ? kebabCase.substr(1) : kebabCase;
|
|
171
174
|
}
|
|
@@ -174,9 +177,9 @@ export function camelCaseToKebabCase(camelCase = ''): string {
|
|
|
174
177
|
* @method camelCase2Underscore
|
|
175
178
|
* @description Transfer CamelCase to Underscore.
|
|
176
179
|
* @param {string} camelCase 'aBC' or 'ABC'
|
|
177
|
-
* @
|
|
178
|
-
|
|
179
|
-
export function camelCase2Underscore(camelCase
|
|
180
|
+
* @returns {string} 'a_b_c'
|
|
181
|
+
*/
|
|
182
|
+
export function camelCase2Underscore(camelCase: string): string {
|
|
180
183
|
const kebabCase = camelCase.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
181
184
|
return kebabCase[0] === '_' ? kebabCase.substr(1) : kebabCase;
|
|
182
185
|
}
|
|
@@ -185,9 +188,9 @@ export function camelCase2Underscore(camelCase = ''): string {
|
|
|
185
188
|
* @method mTrim
|
|
186
189
|
* @description Remove leading and trailing whitespace or specified characters from string.
|
|
187
190
|
* @param {string} str The string to trim.
|
|
188
|
-
* @
|
|
189
|
-
|
|
190
|
-
export function mTrim(str
|
|
191
|
+
* @returns {string} Trimmed string.
|
|
192
|
+
*/
|
|
193
|
+
export function mTrim(str: string): string {
|
|
191
194
|
str = str.replace(/^\s+/, ''); // 去除头部空格
|
|
192
195
|
let end = str.length - 1;
|
|
193
196
|
const ws = /\s/;
|
|
@@ -201,9 +204,9 @@ export function mTrim(str = ''): string {
|
|
|
201
204
|
* @method newLine
|
|
202
205
|
* @description Make a newline of HTML.
|
|
203
206
|
* @param {string} str The string to make a newline.
|
|
204
|
-
* @
|
|
205
|
-
|
|
206
|
-
export function newLine(str
|
|
207
|
+
* @returns {string} A newline with `br`.
|
|
208
|
+
*/
|
|
209
|
+
export function newLine(str: string): string {
|
|
207
210
|
if (!str) {
|
|
208
211
|
return '';
|
|
209
212
|
}
|
|
@@ -215,8 +218,8 @@ export function newLine(str = ''): string {
|
|
|
215
218
|
* @method deepCopyObject
|
|
216
219
|
* @description Clone Object deeply.
|
|
217
220
|
* @param {object} obj The value to clone.
|
|
218
|
-
* @
|
|
219
|
-
|
|
221
|
+
* @returns {object} Returns the deep cloned value.
|
|
222
|
+
*/
|
|
220
223
|
export function deepCopyObject(obj: any): any {
|
|
221
224
|
return JSON.parse(JSON.stringify(obj));
|
|
222
225
|
}
|
|
@@ -225,9 +228,9 @@ export function deepCopyObject(obj: any): any {
|
|
|
225
228
|
* @method isJsonString
|
|
226
229
|
* @description Check whether it is a valid JSON string.
|
|
227
230
|
* @param {string} str The string to check.
|
|
228
|
-
* @
|
|
229
|
-
|
|
230
|
-
export function isJsonString(str
|
|
231
|
+
* @returns {boolean} Return the result of checking.
|
|
232
|
+
*/
|
|
233
|
+
export function isJsonString(str: string): boolean {
|
|
231
234
|
try {
|
|
232
235
|
if (typeof JSON.parse(str) === 'object') {
|
|
233
236
|
return true;
|
|
@@ -242,8 +245,8 @@ export function isJsonString(str = ''): boolean {
|
|
|
242
245
|
* @method generateRndNum
|
|
243
246
|
* @description Produce a random string of number, `generateRndNum(7)` => '7658495'.
|
|
244
247
|
* @param {number} n Length
|
|
245
|
-
* @
|
|
246
|
-
|
|
248
|
+
* @returns {string} Return the random string.
|
|
249
|
+
*/
|
|
247
250
|
export function generateRndNum(n = 5): string {
|
|
248
251
|
let ret = '';
|
|
249
252
|
while (n--) {
|
|
@@ -256,7 +259,7 @@ export function generateRndNum(n = 5): string {
|
|
|
256
259
|
* @method generateUniqueNum
|
|
257
260
|
* @description 根据时间生成唯一标志的数字 mGenerateUniqueNum() => 1538324722364123。
|
|
258
261
|
* @param {number} n 随机数的长度
|
|
259
|
-
|
|
262
|
+
*/
|
|
260
263
|
export function generateUniqueNum(n = 3): string {
|
|
261
264
|
const [now, rnd] = [mNow(), generateRndNum(n || 3)];
|
|
262
265
|
return now + rnd;
|
|
@@ -267,8 +270,8 @@ export function generateUniqueNum(n = 3): string {
|
|
|
267
270
|
* @description 浮点数转为百分比 0.2 => 20%。
|
|
268
271
|
* @param {number} num 浮点数
|
|
269
272
|
* @param {number} fixSize 保留几位浮点数
|
|
270
|
-
|
|
271
|
-
export function floatToPercent(num
|
|
273
|
+
*/
|
|
274
|
+
export function floatToPercent(num: number, fixSize = 0): string {
|
|
272
275
|
let ret = '';
|
|
273
276
|
if (fixSize) {
|
|
274
277
|
ret = (num * 100).toFixed(fixSize);
|
|
@@ -281,7 +284,7 @@ export function floatToPercent(num = 0, fixSize = 0): string {
|
|
|
281
284
|
/**
|
|
282
285
|
* @method floatFixed
|
|
283
286
|
* @description 浮点数保留指定位。
|
|
284
|
-
|
|
287
|
+
*/
|
|
285
288
|
export function floatFixed(num: string, size = 0): string {
|
|
286
289
|
return parseFloat(num).toFixed(size);
|
|
287
290
|
}
|
|
@@ -289,7 +292,7 @@ export function floatFixed(num: string, size = 0): string {
|
|
|
289
292
|
/**
|
|
290
293
|
* @method cancelBubble
|
|
291
294
|
* @description 阻止冒泡。
|
|
292
|
-
|
|
295
|
+
*/
|
|
293
296
|
export function cancelBubble(e: any): void {
|
|
294
297
|
const ev = e || window.event;
|
|
295
298
|
if (ev.stopPropagation) {
|
|
@@ -303,7 +306,7 @@ export function cancelBubble(e: any): void {
|
|
|
303
306
|
|
|
304
307
|
/**
|
|
305
308
|
* @method hasClass
|
|
306
|
-
|
|
309
|
+
*/
|
|
307
310
|
export function hasClass(obj: any, cls: string): boolean {
|
|
308
311
|
const oriCls = obj.className; // 获取对象的class值
|
|
309
312
|
const oriClsArr = oriCls.split(/\s+/); // 分隔空格转换成数组
|
|
@@ -317,7 +320,7 @@ export function hasClass(obj: any, cls: string): boolean {
|
|
|
317
320
|
|
|
318
321
|
/**
|
|
319
322
|
* @method addClass
|
|
320
|
-
|
|
323
|
+
*/
|
|
321
324
|
export function addClass(obj: any, cls: string): void {
|
|
322
325
|
const oriCls = obj.className;
|
|
323
326
|
let space = '';
|
|
@@ -331,7 +334,7 @@ export function addClass(obj: any, cls: string): void {
|
|
|
331
334
|
|
|
332
335
|
/**
|
|
333
336
|
* @method removeClass
|
|
334
|
-
|
|
337
|
+
*/
|
|
335
338
|
export function removeClass(obj: any, cls: string): void {
|
|
336
339
|
const oriCls = obj.className;
|
|
337
340
|
let newCls; // 获取对象的class值
|
|
@@ -343,19 +346,25 @@ export function removeClass(obj: any, cls: string): void {
|
|
|
343
346
|
}
|
|
344
347
|
|
|
345
348
|
/**
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
|
|
349
|
+
* EN: Throttle
|
|
350
|
+
* ZH: 节流
|
|
351
|
+
*
|
|
352
|
+
* @see https://lodash.com/docs/4.17.15#throttle
|
|
353
|
+
*/
|
|
354
|
+
export function throttle(func: any, wait: number, options: { leading?: boolean; trailing?: boolean; } = {}): any {
|
|
355
|
+
options = Object.assign(
|
|
356
|
+
{},
|
|
357
|
+
options,
|
|
358
|
+
);
|
|
350
359
|
// timeout: setTimeout Handle
|
|
351
360
|
// previous: 上次时间戳
|
|
352
361
|
let context: any = null;
|
|
353
362
|
let args: any = null;
|
|
354
363
|
let timeout: any = null;
|
|
355
364
|
let [result, previous] = [null, 0];
|
|
356
|
-
if (!options) {
|
|
357
|
-
|
|
358
|
-
}
|
|
365
|
+
// if (!options) {
|
|
366
|
+
// options = {};
|
|
367
|
+
// }
|
|
359
368
|
const later = function () {
|
|
360
369
|
previous = options.leading === false ? 0 : mNow();
|
|
361
370
|
timeout = null;
|
|
@@ -390,10 +399,11 @@ export function throttle(func: any, wait: number, options: any): any {
|
|
|
390
399
|
}
|
|
391
400
|
|
|
392
401
|
/**
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
|
|
402
|
+
* EN: Debounce
|
|
403
|
+
*
|
|
404
|
+
* ZH: 去抖
|
|
405
|
+
*/
|
|
406
|
+
export function debounce(func: any, wait: number, immediate?: any): any {
|
|
397
407
|
let context: any = null;
|
|
398
408
|
let timeout: any = null;
|
|
399
409
|
let timestamp: any = null;
|
|
@@ -434,14 +444,15 @@ export function debounce(func: any, wait: number, immediate: any): any {
|
|
|
434
444
|
* @description 获取间隔时间。
|
|
435
445
|
* @param {number/Date} start 开始时间戳 1585325367122
|
|
436
446
|
* @param {number/Date} end 结束时间戳 1585325367122
|
|
437
|
-
* @
|
|
438
|
-
* @
|
|
439
|
-
|
|
440
|
-
export function friendlyInterval(start = 0, end = 0, { type = 'd' }
|
|
447
|
+
* @param {string} options.type 返回类型 d: 2(天) text: 2 天 4 时...
|
|
448
|
+
* @returns {String/number} 取决于 type
|
|
449
|
+
*/
|
|
450
|
+
export function friendlyInterval(start = 0, end = 0, options: { type?: string; } = { type: 'd' }): number | string {
|
|
451
|
+
const { type } = options;
|
|
441
452
|
if (!isNumber(start)) start = new Date(start).getTime();
|
|
442
453
|
if (!isNumber(end)) end = new Date(end).getTime();
|
|
443
454
|
const t = end - start;
|
|
444
|
-
let ret =
|
|
455
|
+
let ret = '';
|
|
445
456
|
let [d, h, m, s] = new Array(4).fill(0);
|
|
446
457
|
if (t >= 0) {
|
|
447
458
|
d = Math.floor(t / 1000 / 60 / 60 / 24);
|
|
@@ -470,11 +481,15 @@ export function friendlyInterval(start = 0, end = 0, { type = 'd' } = {}): numbe
|
|
|
470
481
|
* @method isNumber
|
|
471
482
|
* @description 判断是否有效数字
|
|
472
483
|
* @param {*} num 被判断的值
|
|
473
|
-
* @param {boolean} isNaNAsNumber 是否 NaN 算数字(默认不算)
|
|
474
|
-
* @param {boolean} isUnFiniteAsNumber 是否 无限 算数字(默认不算)
|
|
475
|
-
* @
|
|
484
|
+
* @param {boolean} options.isNaNAsNumber 是否 NaN 算数字(默认不算)
|
|
485
|
+
* @param {boolean} options.isUnFiniteAsNumber 是否 无限 算数字(默认不算)
|
|
486
|
+
* @returns {boolean} true 是数字
|
|
476
487
|
*/
|
|
477
|
-
export function isNumber(num: any, { isNaNAsNumber = false, isUnFiniteAsNumber
|
|
488
|
+
export function isNumber(num: any, options: { isNaNAsNumber?: boolean; isUnFiniteAsNumber?: boolean; } = { isNaNAsNumber: false, isUnFiniteAsNumber: false }): boolean {
|
|
489
|
+
const { isNaNAsNumber, isUnFiniteAsNumber } = Object.assign(
|
|
490
|
+
{ isNaNAsNumber: false, isUnFiniteAsNumber: false },
|
|
491
|
+
options,
|
|
492
|
+
);
|
|
478
493
|
let ret = true;
|
|
479
494
|
// 数字类型
|
|
480
495
|
if (typeof num !== 'number') {
|
|
@@ -497,7 +512,7 @@ export function isNumber(num: any, { isNaNAsNumber = false, isUnFiniteAsNumber =
|
|
|
497
512
|
* @method doFn
|
|
498
513
|
* @description 执行有效函数
|
|
499
514
|
* @param {function} fn 等待被执行的未知是否有效的函数
|
|
500
|
-
|
|
515
|
+
*/
|
|
501
516
|
export function doFn(fn: any, ...params: any[]): any {
|
|
502
517
|
let ret = null;
|
|
503
518
|
if (fn && typeof fn === 'function') {
|
|
@@ -511,7 +526,7 @@ export function doFn(fn: any, ...params: any[]): any {
|
|
|
511
526
|
* @description 存储数据到 sessionStorage
|
|
512
527
|
* @param {string} key 键
|
|
513
528
|
* @param {string} value 值
|
|
514
|
-
|
|
529
|
+
*/
|
|
515
530
|
export function setSessionStorage(key: string, value: any = null): void {
|
|
516
531
|
if (key) {
|
|
517
532
|
sessionStorage.setItem(key, JSON.stringify(value));
|
|
@@ -522,8 +537,8 @@ export function setSessionStorage(key: string, value: any = null): void {
|
|
|
522
537
|
* @method getSessionStorage
|
|
523
538
|
* @description 存储数据到 sessionStorage
|
|
524
539
|
* @param {string} key 键
|
|
525
|
-
* @
|
|
526
|
-
|
|
540
|
+
* @returns {*} 返回值
|
|
541
|
+
*/
|
|
527
542
|
export function getSessionStorage(key: string): any {
|
|
528
543
|
let ret = null;
|
|
529
544
|
if (key) {
|
|
@@ -540,7 +555,7 @@ export function getSessionStorage(key: string): any {
|
|
|
540
555
|
* @description 存储数据到 localStorage
|
|
541
556
|
* @param {string} key 键
|
|
542
557
|
* @param {string} value 值
|
|
543
|
-
|
|
558
|
+
*/
|
|
544
559
|
export function setLocalStorage(key: string, value: any = null): void {
|
|
545
560
|
if (key) {
|
|
546
561
|
localStorage.setItem(key, JSON.stringify(value));
|
|
@@ -551,8 +566,8 @@ export function setLocalStorage(key: string, value: any = null): void {
|
|
|
551
566
|
* @method getLocalStorage
|
|
552
567
|
* @description 存储数据到 localStorage
|
|
553
568
|
* @param {string} key 键
|
|
554
|
-
* @
|
|
555
|
-
|
|
569
|
+
* @returns {*} 返回值
|
|
570
|
+
*/
|
|
556
571
|
export function getLocalStorage(key: string): any {
|
|
557
572
|
let ret = null;
|
|
558
573
|
if (key) {
|
|
@@ -568,18 +583,20 @@ export function getLocalStorage(key: string): any {
|
|
|
568
583
|
* @method loadCSS
|
|
569
584
|
* @description 动态加载css文件
|
|
570
585
|
* @param {string} url -- css资源路径
|
|
571
|
-
* @param {string} id -- link标签id
|
|
572
|
-
* @
|
|
586
|
+
* @param {string} options.id -- link标签id
|
|
587
|
+
* @returns {Promise<boolean>} true -- 加载成功
|
|
573
588
|
*/
|
|
574
|
-
export function loadCSS(url
|
|
575
|
-
|
|
576
|
-
let
|
|
589
|
+
export function loadCSS(url: string, options: { id?: string } = { id: '' }): Promise<boolean | Error | any> {
|
|
590
|
+
const { id } = options;
|
|
591
|
+
let success: (v: boolean) => void;
|
|
592
|
+
let fail: (v: Error) => void;
|
|
577
593
|
const status = new Promise((resolve, reject) => {
|
|
578
594
|
([success, fail] = [resolve, reject]);
|
|
579
595
|
});
|
|
580
596
|
// const tempCB = (typeof callback === 'function' ? callback : function () { });
|
|
581
597
|
const callback = function () {
|
|
582
|
-
doFn(success, true);
|
|
598
|
+
// doFn(success, true);
|
|
599
|
+
success(true);
|
|
583
600
|
};
|
|
584
601
|
let node: any = document.createElement('link');
|
|
585
602
|
const supportOnload = 'onload' in node;
|
|
@@ -689,13 +706,22 @@ export function loadCSS(url = '', { id = '' } = {}): Promise<any> {
|
|
|
689
706
|
* @method loadScript
|
|
690
707
|
* @description 动态加载js文件
|
|
691
708
|
* @param {string} url -- js资源路径
|
|
692
|
-
* @param {string} id -- DOM ID
|
|
693
|
-
* @param {function} callback -- 加载后回调函数
|
|
694
|
-
* @param {number} timeout -- 超时时长
|
|
695
|
-
* @param {boolean} isDefer -- 是否添加 defer 标签
|
|
696
|
-
* @
|
|
709
|
+
* @param {string} options.id -- DOM ID
|
|
710
|
+
* @param {function} options.callback -- 加载后回调函数
|
|
711
|
+
* @param {number} options.timeout -- 超时时长
|
|
712
|
+
* @param {boolean} options.isDefer -- 是否添加 defer 标签
|
|
713
|
+
* @returns {Promise<boolean>} -- true 成功
|
|
697
714
|
*/
|
|
698
|
-
export function loadScript(url
|
|
715
|
+
export function loadScript(url: string, options: {
|
|
716
|
+
id: string;
|
|
717
|
+
callback: (...params: any[]) => any;
|
|
718
|
+
timeout: number;
|
|
719
|
+
isDefer: boolean;
|
|
720
|
+
} = { id: '', callback: function () { /* pass */ }, timeout: 5000, isDefer: false }): Promise<boolean | string | Error> {
|
|
721
|
+
const { id, callback, timeout, isDefer } = Object.assign(
|
|
722
|
+
{ id: '', callback: function () { /* pass */ }, timeout: 5000, isDefer: false },
|
|
723
|
+
options,
|
|
724
|
+
);
|
|
699
725
|
let success: any = null;
|
|
700
726
|
let fail: any = null;
|
|
701
727
|
const script: any = document.createElement('script');
|
|
@@ -729,7 +755,7 @@ export function loadScript(url = '', { id = '', callback = function () { /* pass
|
|
|
729
755
|
return new Promise((resolve, reject) => {
|
|
730
756
|
([success, fail] = [resolve, reject]);
|
|
731
757
|
if (timeout) {
|
|
732
|
-
setTimeout(fail.bind(null, 'timeout'), timeout);
|
|
758
|
+
setTimeout(fail.bind(null, Error('timeout')), timeout);
|
|
733
759
|
}
|
|
734
760
|
});
|
|
735
761
|
}
|
|
@@ -807,16 +833,20 @@ export function getCookie(name: string): string {
|
|
|
807
833
|
return '';
|
|
808
834
|
}
|
|
809
835
|
|
|
836
|
+
interface WebPerformance {
|
|
837
|
+
[key: string]: string | number;
|
|
838
|
+
}
|
|
839
|
+
|
|
810
840
|
/**
|
|
811
841
|
* @method getPerformance
|
|
812
842
|
* @description 获取页面加载相关的各项数据
|
|
813
843
|
* @param {boolean} camelCase -- true(默认) 以驼峰形式返回数据 false 以下划线形式返回数据
|
|
814
|
-
* @
|
|
844
|
+
* @returns {Promise<object>} 加载数据
|
|
815
845
|
*/
|
|
816
|
-
export function getPerformance(camelCase = true): Promise<
|
|
817
|
-
let success:
|
|
818
|
-
let fail:
|
|
819
|
-
const status = new Promise((resolve, reject) => {
|
|
846
|
+
export function getPerformance(camelCase = true): Promise<WebPerformance | Error> {
|
|
847
|
+
let success: (v: WebPerformance) => void;
|
|
848
|
+
let fail: (v: Error) => void;
|
|
849
|
+
const status: Promise<WebPerformance> = new Promise((resolve, reject) => {
|
|
820
850
|
([success, fail] = [resolve, reject]);
|
|
821
851
|
});
|
|
822
852
|
const timing = window.performance.timing;
|
|
@@ -909,10 +939,10 @@ export function getPerformance(camelCase = true): Promise<any> {
|
|
|
909
939
|
}
|
|
910
940
|
success(Underscore || data);
|
|
911
941
|
} else {
|
|
912
|
-
fail('startTime');
|
|
942
|
+
fail(Error('startTime'));
|
|
913
943
|
}
|
|
914
944
|
} else {
|
|
915
|
-
fail('getEntries');
|
|
945
|
+
fail(Error('getEntries'));
|
|
916
946
|
}
|
|
917
947
|
}
|
|
918
948
|
//获取当前操作系统
|
|
@@ -1021,7 +1051,7 @@ export function getPerformance(camelCase = true): Promise<any> {
|
|
|
1021
1051
|
* @method inRate
|
|
1022
1052
|
* @description 百分位概率
|
|
1023
1053
|
* @param {number} rate -- 0.1 ~ 1 => 1% ~ 100%
|
|
1024
|
-
* @
|
|
1054
|
+
* @returns {boolean} true 命中
|
|
1025
1055
|
*/
|
|
1026
1056
|
export function inRate(rate: number): boolean {
|
|
1027
1057
|
if(Math.random() < rate) {
|
|
@@ -1033,7 +1063,7 @@ export function inRate(rate: number): boolean {
|
|
|
1033
1063
|
/**
|
|
1034
1064
|
* @method isSafePWAEnv
|
|
1035
1065
|
* @description 判断是否是安全的 PWA 环境
|
|
1036
|
-
* @
|
|
1066
|
+
* @returns {boolean} true 是
|
|
1037
1067
|
*/
|
|
1038
1068
|
export function isSafePWAEnv(): boolean {
|
|
1039
1069
|
// 判断是否支持 async await
|
|
@@ -1076,16 +1106,53 @@ export function isSafePWAEnv(): boolean {
|
|
|
1076
1106
|
}
|
|
1077
1107
|
|
|
1078
1108
|
/**
|
|
1079
|
-
*
|
|
1080
|
-
*
|
|
1081
|
-
*
|
|
1109
|
+
* EN: Browser Information
|
|
1110
|
+
*
|
|
1111
|
+
* ZH: 返回浏览器信息 https://github.com/JowayYoung/juejin-code/blob/master/browser-type.js
|
|
1112
|
+
*
|
|
1113
|
+
* ```
|
|
1114
|
+
* getBrowserInfo(); // {"engine":"webkit","engineVs":"537.36","platform":"desktop","supporter":"chrome","supporterVs":"85.0.4183.121","system":"windows","systemVs":"10"}
|
|
1115
|
+
* ```
|
|
1116
|
+
*
|
|
1117
|
+
* | Index | Field | Description |
|
|
1118
|
+
* | --- | --- | --- |
|
|
1119
|
+
* | System | system | android, ios, windows, macos, linux |
|
|
1120
|
+
* | System version | systemVs | windows: 2000, xp, 2003, vista, 7, 8, 8.1, 10 <br />macos: ... |
|
|
1121
|
+
* | Platform | platform | desktop, mobile |
|
|
1122
|
+
* | Engine | engine | webkit, gecko, presto, trident |
|
|
1123
|
+
* | Engine version | engineVs | - |
|
|
1124
|
+
* | Supporter | supporter | edge, opera, chrome, safari, firefox, iexplore |
|
|
1125
|
+
* | Supporter version | supporterVs | - |
|
|
1126
|
+
* | Shell | shell | (Optional) wechat, qq_browser, qq_app, uc, 360, 2345, sougou, liebao, maxthon, bilibili |
|
|
1127
|
+
* | Shell version | shellVs | (Optional) |
|
|
1128
|
+
* | Apple device type | appleType | (Optional) iphone, ipad, ipod, iwatch |
|
|
1129
|
+
*
|
|
1130
|
+
* Example: Determine the environment of the mobile QQ.
|
|
1131
|
+
*
|
|
1132
|
+
* ```
|
|
1133
|
+
* const { system, shell } = getBrowserInfo();
|
|
1134
|
+
* const isMobileQQ = ['android', 'ios'].includes(system) && ['qq_browser', 'qq_app'].includes(shell);
|
|
1135
|
+
* ```
|
|
1136
|
+
*
|
|
1137
|
+
* @returns 浏览器信息
|
|
1082
1138
|
*/
|
|
1083
|
-
export function getBrowserInfo():
|
|
1139
|
+
export function getBrowserInfo(): {
|
|
1140
|
+
engine: string; // webkit gecko presto trident
|
|
1141
|
+
engineVs: string;
|
|
1142
|
+
platform: string; // desktop mobile
|
|
1143
|
+
supporter: string; // chrome safari firefox opera iexplore edge
|
|
1144
|
+
supporterVs: string;
|
|
1145
|
+
system: string; // windows macos linux android ios
|
|
1146
|
+
systemVs: string;
|
|
1147
|
+
shell?: string; // wechat qq uc 360 2345 sougou liebao maxthon
|
|
1148
|
+
shellVs?: string;
|
|
1149
|
+
appleType?: string;
|
|
1150
|
+
} {
|
|
1084
1151
|
try {
|
|
1085
1152
|
// 权重:系统 + 系统版本 > 平台 > 内核 + 载体 + 内核版本 + 载体版本 > 外壳 + 外壳版本
|
|
1086
|
-
const ua:
|
|
1087
|
-
const testUa: (regexp:
|
|
1088
|
-
const testVs: (regexp:
|
|
1153
|
+
const ua: string = navigator.userAgent.toLowerCase();
|
|
1154
|
+
const testUa: (regexp: RegExp) => boolean = regexp => regexp.test(ua);
|
|
1155
|
+
const testVs: (regexp: RegExp) => string = regexp => {
|
|
1089
1156
|
const matchRes = ua.match(regexp);
|
|
1090
1157
|
let ret = '';
|
|
1091
1158
|
if (matchRes) {
|
|
@@ -1248,18 +1315,26 @@ export function getBrowserInfo(): any {
|
|
|
1248
1315
|
});
|
|
1249
1316
|
} catch (err) {
|
|
1250
1317
|
console.warn('mazey:', err);
|
|
1251
|
-
return {
|
|
1318
|
+
return {
|
|
1319
|
+
engine: '', // webkit gecko presto trident
|
|
1320
|
+
engineVs: '',
|
|
1321
|
+
platform: '', // desktop mobile
|
|
1322
|
+
supporter: '', // chrome safari firefox opera iexplore edge
|
|
1323
|
+
supporterVs: '',
|
|
1324
|
+
system: '', // windows macos linux android ios
|
|
1325
|
+
systemVs: '',
|
|
1326
|
+
};
|
|
1252
1327
|
}
|
|
1253
1328
|
}
|
|
1254
1329
|
|
|
1255
1330
|
/**
|
|
1256
1331
|
* @method clearHtml
|
|
1257
1332
|
* @description 去除HTML标签
|
|
1258
|
-
* @param {string}
|
|
1259
|
-
* @
|
|
1333
|
+
* @param {string} str 带html标签的字符串
|
|
1334
|
+
* @returns {string} 字符串
|
|
1260
1335
|
*/
|
|
1261
|
-
export function clearHtml (string
|
|
1262
|
-
return
|
|
1336
|
+
export function clearHtml (str: string): string {
|
|
1337
|
+
return str.replace(/<\/?.+?>/g, '').replace(/[\r\n]/g, '');
|
|
1263
1338
|
}
|
|
1264
1339
|
|
|
1265
1340
|
/**
|
|
@@ -1268,9 +1343,9 @@ export function clearHtml (string = ''): string {
|
|
|
1268
1343
|
* @param {string} str 要截取的字符串
|
|
1269
1344
|
* @param {number} len
|
|
1270
1345
|
* @param {boolean} hasDot
|
|
1271
|
-
* @
|
|
1346
|
+
* @returnss {string} 返回截取后的字符串
|
|
1272
1347
|
*/
|
|
1273
|
-
export function cutCHSString(str
|
|
1348
|
+
export function cutCHSString(str: string, len: number, hasDot = false): string {
|
|
1274
1349
|
if (str == '' || !str) {
|
|
1275
1350
|
return '';
|
|
1276
1351
|
} else {
|
|
@@ -1304,12 +1379,12 @@ export function cutCHSString(str = '', len = str.length, hasDot = false): string
|
|
|
1304
1379
|
* @method windowLoaded
|
|
1305
1380
|
* @description 页面加载完成
|
|
1306
1381
|
* @param {number} timeout 超时时间 / 单位:秒
|
|
1307
|
-
* @
|
|
1308
|
-
*/
|
|
1309
|
-
export function windowLoaded(timeout = 90): Promise<string> {
|
|
1382
|
+
* @returns {Promise<string>} document is loaded? 'complete' 'load' / 'timeout'
|
|
1383
|
+
*/
|
|
1384
|
+
export function windowLoaded(timeout = 90): Promise<string | Error> {
|
|
1310
1385
|
let loaded: (value: string) => void = () => undefined;
|
|
1311
|
-
let loadFail: (value:
|
|
1312
|
-
const status = new Promise((resolve: (value: string) => void, reject: (value:
|
|
1386
|
+
let loadFail: (value: Error) => void;
|
|
1387
|
+
const status = new Promise((resolve: (value: string) => void, reject: (value: Error) => void) => {
|
|
1313
1388
|
loaded = resolve;
|
|
1314
1389
|
loadFail = reject;
|
|
1315
1390
|
});
|
|
@@ -1319,42 +1394,83 @@ export function windowLoaded(timeout = 90): Promise<string> {
|
|
|
1319
1394
|
window.addEventListener('load', () => loaded('load'));
|
|
1320
1395
|
}
|
|
1321
1396
|
// 超过 timeout 秒后加载失败
|
|
1322
|
-
setTimeout(() => loadFail('timeout'), timeout * 1000);
|
|
1397
|
+
setTimeout(() => loadFail(Error('timeout')), timeout * 1000);
|
|
1323
1398
|
return status;
|
|
1324
1399
|
}
|
|
1325
1400
|
|
|
1326
1401
|
/**
|
|
1327
|
-
*
|
|
1328
|
-
*
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1402
|
+
* EN: Add `<style>` in `<head>`.
|
|
1403
|
+
*
|
|
1404
|
+
* ZH: 添加样式标签; style: 样式标签内的字符串; id: `<style>` 标签的 `id`; 返回: 添加成功/失败.
|
|
1405
|
+
*
|
|
1406
|
+
* Example 1: Add the `<style>` with `id`, and repeated invoking will update the content instead of adding a new one.
|
|
1407
|
+
*
|
|
1408
|
+
* ```
|
|
1409
|
+
* addStyle(
|
|
1410
|
+
* `
|
|
1411
|
+
* body {
|
|
1412
|
+
* background-color: #333;
|
|
1413
|
+
* }
|
|
1414
|
+
* `,
|
|
1415
|
+
* {
|
|
1416
|
+
* id: 'test',
|
|
1417
|
+
* }
|
|
1418
|
+
* );
|
|
1419
|
+
* // <style id="test">
|
|
1420
|
+
* // body {
|
|
1421
|
+
* // background-color: #333;
|
|
1422
|
+
* // }
|
|
1423
|
+
* // </style>
|
|
1424
|
+
* ```
|
|
1425
|
+
*
|
|
1426
|
+
* Example 2: Add the `<style>` without `id`, and repeated invoking will adding a new one.
|
|
1427
|
+
*
|
|
1428
|
+
* ```
|
|
1429
|
+
* addStyle(
|
|
1430
|
+
* `
|
|
1431
|
+
* body {
|
|
1432
|
+
* background-color: #333;
|
|
1433
|
+
* }
|
|
1434
|
+
* `
|
|
1435
|
+
* );
|
|
1436
|
+
* // <style>
|
|
1437
|
+
* // body {
|
|
1438
|
+
* // background-color: #333;
|
|
1439
|
+
* // }
|
|
1440
|
+
* // </style>
|
|
1441
|
+
* ```
|
|
1442
|
+
*
|
|
1443
|
+
* @param style Style string.
|
|
1444
|
+
* @param options.id `id` in `<style>`
|
|
1445
|
+
* @returns Success/Fail
|
|
1446
|
+
*/
|
|
1447
|
+
export function addStyle(style: string, options: { id?: string; } = { id: '' }): boolean {
|
|
1448
|
+
// console.log('_ style', style);
|
|
1449
|
+
// console.log('_ options', options);
|
|
1450
|
+
if (!style) {
|
|
1335
1451
|
return false;
|
|
1336
1452
|
}
|
|
1337
1453
|
// 创建 style 文档碎片
|
|
1338
1454
|
const styleFrag = document.createDocumentFragment();
|
|
1339
|
-
let idDom = null;
|
|
1455
|
+
let idDom: HTMLElement | null = null;
|
|
1340
1456
|
let domId = '';
|
|
1341
1457
|
// Custom Style
|
|
1342
1458
|
const customStyle = document.createElement('style');
|
|
1343
1459
|
// 如果需要 ID
|
|
1344
|
-
if (id) {
|
|
1345
|
-
domId = `${id}`;
|
|
1460
|
+
if (options.id) {
|
|
1461
|
+
domId = `${options.id}`;
|
|
1346
1462
|
idDom = document.getElementById(domId);
|
|
1347
1463
|
// 如果 Dom 不存在,插入 style
|
|
1348
1464
|
if (!idDom) {
|
|
1349
|
-
customStyle.setAttribute('id', id);
|
|
1350
|
-
customStyle.innerHTML =
|
|
1465
|
+
customStyle.setAttribute('id', options.id);
|
|
1466
|
+
customStyle.innerHTML = style;
|
|
1351
1467
|
styleFrag.appendChild(customStyle);
|
|
1352
1468
|
document.head.appendChild(styleFrag);
|
|
1353
1469
|
} else { // 如果 Dom 存在,直接更新
|
|
1354
|
-
idDom.innerHTML =
|
|
1470
|
+
idDom.innerHTML = style;
|
|
1355
1471
|
}
|
|
1356
1472
|
} else { // 不需要 ID,直接添加新标签
|
|
1357
|
-
customStyle.innerHTML =
|
|
1473
|
+
customStyle.innerHTML = style;
|
|
1358
1474
|
styleFrag.appendChild(customStyle);
|
|
1359
1475
|
document.head.appendChild(styleFrag);
|
|
1360
1476
|
}
|
|
@@ -1366,9 +1482,9 @@ export function addInlineStyle(inlineStyle = '', { id = '' } = {}): boolean {
|
|
|
1366
1482
|
* @description 生成自定义控制台打印
|
|
1367
1483
|
* @param {string} prefix 前缀
|
|
1368
1484
|
* @param {function} allowFn 允许打印的判断函数
|
|
1369
|
-
* @
|
|
1370
|
-
*/
|
|
1371
|
-
export function genCustomConsole(prefix = ''):
|
|
1485
|
+
* @returns {object} 新实例
|
|
1486
|
+
*/
|
|
1487
|
+
export function genCustomConsole(prefix = ''): Console {
|
|
1372
1488
|
const methods = ['log', 'info', 'warn', 'error'];
|
|
1373
1489
|
const newConsole = Object.create(null);
|
|
1374
1490
|
methods.forEach(method => {
|
|
@@ -1382,3 +1498,98 @@ export function genCustomConsole(prefix = ''): any {
|
|
|
1382
1498
|
});
|
|
1383
1499
|
return newConsole;
|
|
1384
1500
|
}
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* Verify the validity of axios response.
|
|
1504
|
+
*/
|
|
1505
|
+
export function zAxiosIsValidRes(res: any, options: {
|
|
1506
|
+
validStatus: number[];
|
|
1507
|
+
validCode: number[];
|
|
1508
|
+
} = {
|
|
1509
|
+
validStatus: [200],
|
|
1510
|
+
validCode: [0],
|
|
1511
|
+
}): boolean {
|
|
1512
|
+
const { validStatus, validCode } = Object.assign(
|
|
1513
|
+
{
|
|
1514
|
+
validStatus: [200],
|
|
1515
|
+
validCode: [0],
|
|
1516
|
+
},
|
|
1517
|
+
options,
|
|
1518
|
+
);
|
|
1519
|
+
let ret = false;
|
|
1520
|
+
if (res && res.status && validStatus.includes(res.status)) {
|
|
1521
|
+
ret = true;
|
|
1522
|
+
const resData = res.data;
|
|
1523
|
+
if (resData && validCode.includes(resData.code)) {
|
|
1524
|
+
ret = true;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return ret;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* Verify the validity of a non-empty array.
|
|
1532
|
+
*/
|
|
1533
|
+
export function isNonEmptyArray(arr: any[]): boolean {
|
|
1534
|
+
let ret = false;
|
|
1535
|
+
if (Array.isArray(arr) && arr.length) {
|
|
1536
|
+
ret = true;
|
|
1537
|
+
}
|
|
1538
|
+
return ret;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* 语义化文件大小, 把字节转换成正常文件大小.
|
|
1543
|
+
*/
|
|
1544
|
+
export function getFileSize(size: number): string {
|
|
1545
|
+
const toCeilStr: (v: number) => string = n => String(Math.ceil(n));
|
|
1546
|
+
if (!size) return '';
|
|
1547
|
+
const num = 1024.0; // byte
|
|
1548
|
+
if (size < num) {
|
|
1549
|
+
return size + ' B';
|
|
1550
|
+
}
|
|
1551
|
+
if (size < Math.pow(num, 2)) {
|
|
1552
|
+
return toCeilStr(size / num) + ' KB';
|
|
1553
|
+
} // kb
|
|
1554
|
+
if (size < Math.pow(num, 3)) {
|
|
1555
|
+
return toCeilStr(size / Math.pow(num, 2)) + ' MB';
|
|
1556
|
+
} // M
|
|
1557
|
+
if (size < Math.pow(num, 4)) {
|
|
1558
|
+
return toCeilStr(size / Math.pow(num, 3)) + ' G';
|
|
1559
|
+
} // G
|
|
1560
|
+
return toCeilStr(size / Math.pow(num, 4)) + ' T';
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Detect webp support.
|
|
1565
|
+
*
|
|
1566
|
+
* @see https://davidwalsh.name/detect-webp
|
|
1567
|
+
*/
|
|
1568
|
+
export function isSupportWebp(): Promise<boolean> {
|
|
1569
|
+
const fn = (resolve: (v: boolean) => void) => {
|
|
1570
|
+
const img = new Image();
|
|
1571
|
+
img.onload = () => {
|
|
1572
|
+
resolve(img.width > 0 && img.height > 0);
|
|
1573
|
+
};
|
|
1574
|
+
img.onerror = () => {
|
|
1575
|
+
resolve(false);
|
|
1576
|
+
};
|
|
1577
|
+
img.src = "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=";
|
|
1578
|
+
};
|
|
1579
|
+
return new Promise(fn);
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
/**
|
|
1583
|
+
* Generate a Hash Code from a string.
|
|
1584
|
+
*
|
|
1585
|
+
* @see https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery
|
|
1586
|
+
*/
|
|
1587
|
+
export function genHashCode(str: string): number {
|
|
1588
|
+
let hash = 0, i, chr;
|
|
1589
|
+
for (i = 0; i < str.length; i++) {
|
|
1590
|
+
chr = str.charCodeAt(i);
|
|
1591
|
+
hash = ((hash << 5) - hash) + chr;
|
|
1592
|
+
hash |= 0;
|
|
1593
|
+
}
|
|
1594
|
+
return hash;
|
|
1595
|
+
}
|