1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | class NavUA {
|
7 | public _ua: string
|
8 |
|
9 |
|
10 | public isOldEdge: boolean
|
11 |
|
12 |
|
13 | public isFirefox: boolean
|
14 |
|
15 | constructor() {
|
16 | this._ua = navigator.userAgent
|
17 |
|
18 | const math = this._ua.match(/(Edge?)\/(\d+)/)
|
19 | this.isOldEdge = math && math[1] == 'Edge' && parseInt(math[2]) < 19 ? true : false
|
20 |
|
21 | this.isFirefox =
|
22 | /Firefox\/\d+/.test(this._ua) && !/Seamonkey\/\d+/.test(this._ua) ? true : false
|
23 | }
|
24 |
|
25 |
|
26 | public isIE() {
|
27 | return 'ActiveXObject' in window
|
28 | }
|
29 |
|
30 |
|
31 | public isWebkit() {
|
32 | return /webkit/i.test(this._ua)
|
33 | }
|
34 | }
|
35 |
|
36 |
|
37 | export const UA = new NavUA()
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | export function getRandom(prefix: string = ''): string {
|
44 | return prefix + Math.random().toString().slice(2)
|
45 | }
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | export function replaceHtmlSymbol(html: string) {
|
52 | return html
|
53 | .replace(/</gm, '<')
|
54 | .replace(/>/gm, '>')
|
55 | .replace(/"/gm, '"')
|
56 | .replace(/(\r\n|\r|\n)/g, '<br/>')
|
57 | }
|
58 |
|
59 | export function replaceSpecialSymbol(value: string) {
|
60 | return value
|
61 | .replace(/</gm, '<')
|
62 | .replace(/>/gm, '>')
|
63 | .replace(/"/gm, '"')
|
64 | }
|
65 |
|
66 | interface Obj {
|
67 | [key: string]: unknown
|
68 | [key: number]: unknown
|
69 | }
|
70 | interface ArrObj {
|
71 | length: number
|
72 | [key: number]: unknown
|
73 | }
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 | export function forEach<T extends ArrObj, V = T[Extract<keyof T, number>]>(
|
81 | obj: T,
|
82 | fn: (key: string, value: V) => boolean | void
|
83 | ): void
|
84 | export function forEach<T extends Obj>(
|
85 | obj: T,
|
86 | fn: (key: string, value: T[Extract<keyof T, string | number>]) => boolean | void
|
87 | ): void
|
88 | export function forEach<T extends unknown[]>(
|
89 | obj: T,
|
90 | fn: (key: string, value: T[Extract<keyof T, number>]) => boolean | void
|
91 | ): void
|
92 | export function forEach<T extends unknown[] | Obj | ArrObj>(
|
93 | obj: T,
|
94 | fn: (
|
95 | key: string,
|
96 | value: T[Extract<keyof T, number>] | T[Extract<keyof T, string>]
|
97 | ) => boolean | void
|
98 | ): void {
|
99 | for (let key in obj) {
|
100 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
101 | const result = fn(key, obj[key])
|
102 | if (result === false) {
|
103 |
|
104 | break
|
105 | }
|
106 | }
|
107 | }
|
108 | }
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | export function arrForEach<T extends { length: number; [key: number]: unknown }>(
|
116 | fakeArr: T,
|
117 | fn: (this: T, item: T[number], index: number) => boolean | unknown
|
118 | ): void {
|
119 | let i, item, result
|
120 | const length = fakeArr.length || 0
|
121 | for (i = 0; i < length; i++) {
|
122 | item = fakeArr[i]
|
123 | result = fn.call(fakeArr, item, i)
|
124 | if (result === false) {
|
125 | break
|
126 | }
|
127 | }
|
128 | }
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 | export function throttle<C, T extends unknown[]>(
|
137 | fn: (this: C, ...args: T) => unknown,
|
138 | interval: number = 200
|
139 | ) {
|
140 | let flag = false
|
141 | return function (this: C, ...args: T): void {
|
142 | if (!flag) {
|
143 | flag = true
|
144 | setTimeout(() => {
|
145 | flag = false
|
146 | fn.call(this, ...args)
|
147 | }, interval)
|
148 | }
|
149 | }
|
150 | }
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 | export function debounce<C, T extends unknown[]>(
|
158 | fn: (this: C, ...args: T) => void,
|
159 | delay: number = 200
|
160 | ): (this: C, ...args: T) => void {
|
161 | let lastFn = 0
|
162 | return function (...args: T) {
|
163 | if (lastFn) {
|
164 | window.clearTimeout(lastFn)
|
165 | }
|
166 | lastFn = window.setTimeout(() => {
|
167 | lastFn = 0
|
168 | fn.call(this, ...args)
|
169 | }, delay)
|
170 | }
|
171 | }
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | export function isFunction(fn: any): fn is Function {
|
178 | return typeof fn === 'function'
|
179 | }
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 | export function deepClone<T>(data: T): T {
|
186 | if (typeof data !== 'object' || typeof data == 'function' || data === null) {
|
187 | return data
|
188 | }
|
189 |
|
190 | let item: any
|
191 | if (Array.isArray(data)) {
|
192 | item = []
|
193 | }
|
194 |
|
195 | if (!Array.isArray(data)) {
|
196 | item = {}
|
197 | }
|
198 |
|
199 | for (let i in data) {
|
200 | if (Object.prototype.hasOwnProperty.call(data, i)) {
|
201 | item[i] = deepClone(data[i])
|
202 | }
|
203 | }
|
204 |
|
205 | return item
|
206 | }
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 | export function toArray<T>(data: T) {
|
213 | return Array.prototype.slice.call(data)
|
214 | }
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | export function getRandomCode() {
|
221 | return Math.random().toString(36).slice(-5)
|
222 | }
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 | export function hexToRgb(hex: string) {
|
229 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
230 |
|
231 | if (result == null) return null
|
232 |
|
233 | const colors = result.map(i => parseInt(i, 16))
|
234 | const r = colors[1]
|
235 | const g = colors[2]
|
236 | const b = colors[3]
|
237 |
|
238 | return `rgb(${r}, ${g}, ${b})`
|
239 | }
|