@whitesev/domutils 1.0.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/dist/index.cjs.js +1677 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +1675 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +1683 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/src/CommonDOMUtils.d.ts +36 -0
- package/dist/src/Core.d.ts +197 -0
- package/dist/src/DOMUtils.d.ts +877 -0
- package/dist/src/Data.d.ts +5 -0
- package/dist/src/OriginPrototype.d.ts +6 -0
- package/global.d.ts +1 -0
- package/index.ts +3 -0
- package/package.json +34 -0
- package/rollup.config.js +28 -0
- package/src/CommonDOMUtils.ts +96 -0
- package/src/Core.ts +224 -0
- package/src/DOMUtils.ts +2504 -0
- package/src/Data.ts +9 -0
- package/src/OriginPrototype.ts +7 -0
- package/tsconfig.json +31 -0
package/src/DOMUtils.ts
ADDED
|
@@ -0,0 +1,2504 @@
|
|
|
1
|
+
import { CommonDOMUtils } from "./CommonDOMUtils";
|
|
2
|
+
import { DOMUtilsData } from "./Data";
|
|
3
|
+
import { OriginPrototype } from "./OriginPrototype";
|
|
4
|
+
|
|
5
|
+
class DOMUtils {
|
|
6
|
+
/** 版本号 */
|
|
7
|
+
version = "2024.5.24";
|
|
8
|
+
/**
|
|
9
|
+
* 获取元素的属性值
|
|
10
|
+
* @param element 目标元素
|
|
11
|
+
* @param attrName 属性名
|
|
12
|
+
* @example
|
|
13
|
+
* // 获取a.xx元素的href属性
|
|
14
|
+
* DOMUtils.attr(document.querySelector("a.xx"),"href");
|
|
15
|
+
* DOMUtils.attr("a.xx","href");
|
|
16
|
+
* > https://xxxx....
|
|
17
|
+
*/
|
|
18
|
+
attr(element: HTMLElement | string, attrName: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* 设置元素的属性值
|
|
21
|
+
* @param element 目标元素
|
|
22
|
+
* @param attrName 属性名
|
|
23
|
+
* @param attrValue 属性值
|
|
24
|
+
* @example
|
|
25
|
+
* // 修改a.xx元素的href属性为abcd
|
|
26
|
+
* DOMUtils.attr(document.querySelector("a.xx"),"href","abcd");
|
|
27
|
+
* DOMUtils.attr("a.xx","href","abcd");
|
|
28
|
+
*/
|
|
29
|
+
attr(
|
|
30
|
+
element: HTMLElement | string,
|
|
31
|
+
attrName: string,
|
|
32
|
+
attrValue: string
|
|
33
|
+
): void;
|
|
34
|
+
attr(element: HTMLElement | string, attrName: string, attrValue?: string) {
|
|
35
|
+
if (typeof element === "string") {
|
|
36
|
+
element = document.querySelector(element) as HTMLElement;
|
|
37
|
+
}
|
|
38
|
+
if (element == null) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (attrValue == null) {
|
|
42
|
+
return element.getAttribute(attrName);
|
|
43
|
+
} else {
|
|
44
|
+
element.setAttribute(attrName, attrValue);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 创建元素
|
|
49
|
+
* @param tagName 标签名
|
|
50
|
+
* @param property 属性
|
|
51
|
+
* @param attributes 元素上的自定义属性
|
|
52
|
+
* @example
|
|
53
|
+
* // 创建一个DIV元素,且属性class为xxx
|
|
54
|
+
* DOMUtils.createElement("div",undefined,{ class:"xxx" });
|
|
55
|
+
* > <div class="xxx"></div>
|
|
56
|
+
* @example
|
|
57
|
+
* // 创建一个DIV元素
|
|
58
|
+
* DOMUtils.createElement("div");
|
|
59
|
+
* > <div></div>
|
|
60
|
+
* @example
|
|
61
|
+
* // 创建一个DIV元素
|
|
62
|
+
* DOMUtils.createElement("div","测试");
|
|
63
|
+
* > <div>测试</div>
|
|
64
|
+
*/
|
|
65
|
+
createElement<K extends keyof HTMLElementTagNameMap>(
|
|
66
|
+
/** 元素名 */
|
|
67
|
+
tagName: K,
|
|
68
|
+
/** 属性 */
|
|
69
|
+
property?:
|
|
70
|
+
| ({
|
|
71
|
+
[P in keyof HTMLElementTagNameMap[K]]?: HTMLElementTagNameMap[K][P];
|
|
72
|
+
} & {
|
|
73
|
+
[key: string]: any;
|
|
74
|
+
})
|
|
75
|
+
| string,
|
|
76
|
+
/** 自定义属性 */
|
|
77
|
+
attributes?: DOMUtilsCreateElementAttributesMap
|
|
78
|
+
): HTMLElementTagNameMap[K] {
|
|
79
|
+
let tempElement = document.createElement(tagName);
|
|
80
|
+
if (typeof property === "string") {
|
|
81
|
+
tempElement.innerHTML = property;
|
|
82
|
+
return tempElement;
|
|
83
|
+
}
|
|
84
|
+
if (property == null) {
|
|
85
|
+
property = {};
|
|
86
|
+
}
|
|
87
|
+
if (attributes == null) {
|
|
88
|
+
attributes = {};
|
|
89
|
+
}
|
|
90
|
+
Object.keys(property).forEach((key) => {
|
|
91
|
+
let value = property[key];
|
|
92
|
+
(tempElement as any)[key] = value;
|
|
93
|
+
});
|
|
94
|
+
Object.keys(attributes).forEach((key) => {
|
|
95
|
+
let value = attributes[key];
|
|
96
|
+
if (typeof value === "object") {
|
|
97
|
+
/* object转字符串 */
|
|
98
|
+
value = JSON.stringify(value);
|
|
99
|
+
} else if (typeof value === "function") {
|
|
100
|
+
/* function转字符串 */
|
|
101
|
+
value = value.toString();
|
|
102
|
+
}
|
|
103
|
+
tempElement.setAttribute(key, value);
|
|
104
|
+
});
|
|
105
|
+
return tempElement;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 获取元素的样式属性值
|
|
110
|
+
* @param element 目标元素
|
|
111
|
+
* @param property 样式属性名或包含多个属性名和属性值的对象
|
|
112
|
+
* @example
|
|
113
|
+
* // 获取元素a.xx的CSS属性display
|
|
114
|
+
* DOMUtils.css(document.querySelector("a.xx"),"display");
|
|
115
|
+
* DOMUtils.css("a.xx","display");
|
|
116
|
+
* > "none"
|
|
117
|
+
* */
|
|
118
|
+
css(
|
|
119
|
+
element: HTMLElement | string,
|
|
120
|
+
property: keyof CSSStyleDeclaration & string
|
|
121
|
+
): string;
|
|
122
|
+
/**
|
|
123
|
+
* 设置元素的样式属性
|
|
124
|
+
* @param element 目标元素
|
|
125
|
+
* @param property 样式属性名或包含多个属性名和属性值的对象
|
|
126
|
+
* @param value 样式属性值
|
|
127
|
+
* @example
|
|
128
|
+
* // 设置元素a.xx的CSS属性display为block
|
|
129
|
+
* DOMUtils.css(document.querySelector("a.xx"),"display","block");
|
|
130
|
+
* DOMUtils.css(document.querySelector("a.xx"),"display","block !important");
|
|
131
|
+
* DOMUtils.css("a.xx","display","block");
|
|
132
|
+
* DOMUtils.css("a.xx","display","block !important");
|
|
133
|
+
* @example
|
|
134
|
+
* // 设置元素a.xx的CSS属性top为10px
|
|
135
|
+
* DOMUtils.css(document.querySelector("a.xx"),"top","10px");
|
|
136
|
+
* DOMUtils.css(document.querySelector("a.xx"),"top",10);
|
|
137
|
+
* */
|
|
138
|
+
css(
|
|
139
|
+
element: HTMLElement | string,
|
|
140
|
+
property: keyof CSSStyleDeclaration & string,
|
|
141
|
+
value: string | number
|
|
142
|
+
): string;
|
|
143
|
+
/**
|
|
144
|
+
* 设置元素的样式属性
|
|
145
|
+
* @param element 目标元素
|
|
146
|
+
* @param property 样式属性名或包含多个属性名和属性值的对象
|
|
147
|
+
* @param value 样式属性值
|
|
148
|
+
* @example
|
|
149
|
+
* // 设置元素a.xx的CSS属性display为block
|
|
150
|
+
* DOMUtils.css(document.querySelector("a.xx"),{ display: "block" }});
|
|
151
|
+
* DOMUtils.css(document.querySelector("a.xx"),{ display: "block !important" }});
|
|
152
|
+
* @example
|
|
153
|
+
* // 设置元素a.xx的CSS属性top为10px
|
|
154
|
+
* DOMUtils.css(document.querySelector("a.xx"),{ top: "10px" });
|
|
155
|
+
* DOMUtils.css(document.querySelector("a.xx"),{ top: 10 });
|
|
156
|
+
* */
|
|
157
|
+
css(
|
|
158
|
+
element: HTMLElement | string,
|
|
159
|
+
property: {
|
|
160
|
+
[P in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[P];
|
|
161
|
+
}
|
|
162
|
+
): string;
|
|
163
|
+
css(
|
|
164
|
+
element: HTMLElement | string,
|
|
165
|
+
property:
|
|
166
|
+
| keyof CSSStyleDeclaration
|
|
167
|
+
| string
|
|
168
|
+
| {
|
|
169
|
+
[P in keyof CSSStyleDeclaration]?:
|
|
170
|
+
| string
|
|
171
|
+
| number
|
|
172
|
+
| CSSStyleDeclaration[P];
|
|
173
|
+
},
|
|
174
|
+
value?: string | number
|
|
175
|
+
) {
|
|
176
|
+
/**
|
|
177
|
+
* 把纯数字没有px的加上
|
|
178
|
+
*/
|
|
179
|
+
function handlePixe(propertyName: string, propertyValue: string | number) {
|
|
180
|
+
let allowAddPixe = [
|
|
181
|
+
"width",
|
|
182
|
+
"height",
|
|
183
|
+
"top",
|
|
184
|
+
"left",
|
|
185
|
+
"right",
|
|
186
|
+
"bottom",
|
|
187
|
+
"font-size",
|
|
188
|
+
];
|
|
189
|
+
if (typeof propertyValue === "number") {
|
|
190
|
+
propertyValue = propertyValue.toString();
|
|
191
|
+
}
|
|
192
|
+
if (
|
|
193
|
+
typeof propertyValue === "string" &&
|
|
194
|
+
allowAddPixe.includes(propertyName) &&
|
|
195
|
+
propertyValue.match(/[0-9]$/gi)
|
|
196
|
+
) {
|
|
197
|
+
propertyValue = propertyValue + "px";
|
|
198
|
+
}
|
|
199
|
+
return propertyValue;
|
|
200
|
+
}
|
|
201
|
+
if (typeof element === "string") {
|
|
202
|
+
element = document.querySelector(element) as HTMLElement;
|
|
203
|
+
}
|
|
204
|
+
if (element == null) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (typeof property === "string") {
|
|
208
|
+
if (value == null) {
|
|
209
|
+
return getComputedStyle(element).getPropertyValue(property);
|
|
210
|
+
} else {
|
|
211
|
+
if (value === "string" && value.includes("!important")) {
|
|
212
|
+
element.style.setProperty(property, value, "important");
|
|
213
|
+
} else {
|
|
214
|
+
value = handlePixe(property, value);
|
|
215
|
+
element.style.setProperty(property, value);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} else if (typeof property === "object") {
|
|
219
|
+
for (let prop in property) {
|
|
220
|
+
if (
|
|
221
|
+
typeof property[prop] === "string" &&
|
|
222
|
+
(property[prop] as string).includes("!important")
|
|
223
|
+
) {
|
|
224
|
+
element.style.setProperty(
|
|
225
|
+
prop,
|
|
226
|
+
property[prop] as string,
|
|
227
|
+
"important"
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
property[prop] = handlePixe(prop, property[prop] as string);
|
|
231
|
+
element.style.setProperty(prop, property[prop] as string);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 获取元素的文本内容
|
|
238
|
+
* @param element 目标元素
|
|
239
|
+
* @param text (可选)文本内容
|
|
240
|
+
* @returns 如果传入了text,则返回undefined;否则返回文本内容
|
|
241
|
+
* @example
|
|
242
|
+
* // 设置元素a.xx的文本内容为abcd
|
|
243
|
+
* DOMUtils.text(document.querySelector("a.xx"),"abcd")
|
|
244
|
+
* DOMUtils.text("a.xx","abcd")
|
|
245
|
+
* DOMUtils.text("a.xx",document.querySelector("b"))
|
|
246
|
+
* */
|
|
247
|
+
text(element: HTMLElement | string): string;
|
|
248
|
+
/**
|
|
249
|
+
* 设置元素的文本内容
|
|
250
|
+
* @param element 目标元素
|
|
251
|
+
* @param text (可选)文本内容
|
|
252
|
+
* @returns 如果传入了text,则返回undefined;否则返回文本内容
|
|
253
|
+
* @example
|
|
254
|
+
* // 设置元素a.xx的文本内容为abcd
|
|
255
|
+
* DOMUtils.text(document.querySelector("a.xx"),"abcd")
|
|
256
|
+
* DOMUtils.text("a.xx","abcd")
|
|
257
|
+
* DOMUtils.text("a.xx",document.querySelector("b"))
|
|
258
|
+
* */
|
|
259
|
+
text(
|
|
260
|
+
element: HTMLElement | string,
|
|
261
|
+
text: string | HTMLElement | Element
|
|
262
|
+
): void;
|
|
263
|
+
text(element: HTMLElement | string, text?: string | HTMLElement | Element) {
|
|
264
|
+
if (typeof element === "string") {
|
|
265
|
+
element = document.querySelector(element) as HTMLElement;
|
|
266
|
+
}
|
|
267
|
+
if (element == null) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (text == null) {
|
|
271
|
+
return element.textContent || element.innerText;
|
|
272
|
+
} else {
|
|
273
|
+
if (text instanceof Node) {
|
|
274
|
+
text = text.textContent || (text as HTMLElement).innerText;
|
|
275
|
+
}
|
|
276
|
+
if ("textContent" in element) {
|
|
277
|
+
element.textContent = text as string;
|
|
278
|
+
} else if ("innerText" in element) {
|
|
279
|
+
(element as HTMLElement).innerText = text as string;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 设置元素的HTML内容
|
|
286
|
+
* @param element 目标元素
|
|
287
|
+
* @param html (可选)HTML内容|元素
|
|
288
|
+
* @returns 如果传入了html,则返回undefined;否则返回HTML内容
|
|
289
|
+
* @example
|
|
290
|
+
* // 设置元素a.xx的文本内容为<b>abcd</b>
|
|
291
|
+
* DOMUtils.html(document.querySelector("a.xx"),"<b>abcd</b>")
|
|
292
|
+
* DOMUtils.html("a.xx","<b>abcd</b>")
|
|
293
|
+
* DOMUtils.html("a.xx",document.querySelector("b"))
|
|
294
|
+
* */
|
|
295
|
+
html(
|
|
296
|
+
element: HTMLElement | string,
|
|
297
|
+
html: string | HTMLElement | Element
|
|
298
|
+
): void;
|
|
299
|
+
/**
|
|
300
|
+
* 获取元素的HTML内容
|
|
301
|
+
* @param element 目标元素
|
|
302
|
+
* @param html (可选)HTML内容|元素
|
|
303
|
+
* @returns 如果传入了html,则返回undefined;否则返回HTML内容
|
|
304
|
+
* @example
|
|
305
|
+
* // 设置元素a.xx的文本内容为<b>abcd</b>
|
|
306
|
+
* DOMUtils.html(document.querySelector("a.xx"),"<b>abcd</b>")
|
|
307
|
+
* DOMUtils.html("a.xx","<b>abcd</b>")
|
|
308
|
+
* DOMUtils.html("a.xx",document.querySelector("b"))
|
|
309
|
+
* */
|
|
310
|
+
html(element: HTMLElement | string): string;
|
|
311
|
+
html(element: HTMLElement | string, html?: string | HTMLElement | Element) {
|
|
312
|
+
if (typeof element === "string") {
|
|
313
|
+
element = document.querySelector(element) as HTMLElement;
|
|
314
|
+
}
|
|
315
|
+
if (element == null) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (html == null) {
|
|
319
|
+
return element.innerHTML;
|
|
320
|
+
} else {
|
|
321
|
+
if (html instanceof Node) {
|
|
322
|
+
html = html.innerHTML;
|
|
323
|
+
}
|
|
324
|
+
if ("innerHTML" in element) {
|
|
325
|
+
element.innerHTML = html;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* 绑定或触发元素的click事件
|
|
332
|
+
* @param element 目标元素
|
|
333
|
+
* @param handler (可选)事件处理函数
|
|
334
|
+
* @param details (可选)赋予触发的Event的额外属性
|
|
335
|
+
* @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
|
|
336
|
+
* @example
|
|
337
|
+
* // 触发元素a.xx的click事件
|
|
338
|
+
* DOMUtils.click(document.querySelector("a.xx"))
|
|
339
|
+
* DOMUtils.click("a.xx")
|
|
340
|
+
* DOMUtils.click("a.xx",function(){
|
|
341
|
+
* console.log("触发click事件成功")
|
|
342
|
+
* })
|
|
343
|
+
* */
|
|
344
|
+
click(
|
|
345
|
+
element: HTMLElement | string | Window,
|
|
346
|
+
handler?: (event: PointerEvent | MouseEvent) => void,
|
|
347
|
+
details?: object,
|
|
348
|
+
useDispatchToTriggerEvent?: boolean
|
|
349
|
+
) {
|
|
350
|
+
let DOMUtilsContext = this;
|
|
351
|
+
if (typeof element === "string") {
|
|
352
|
+
element = document.querySelector(element) as HTMLElement;
|
|
353
|
+
}
|
|
354
|
+
if (element == null) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (handler == null) {
|
|
358
|
+
DOMUtilsContext.trigger(
|
|
359
|
+
element,
|
|
360
|
+
"click",
|
|
361
|
+
details,
|
|
362
|
+
useDispatchToTriggerEvent
|
|
363
|
+
);
|
|
364
|
+
} else {
|
|
365
|
+
DOMUtilsContext.on(element, "click", null, handler);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* 绑定或触发元素的blur事件
|
|
370
|
+
* @param element 目标元素
|
|
371
|
+
* @param handler (可选)事件处理函数
|
|
372
|
+
* @param details (可选)赋予触发的Event的额外属性
|
|
373
|
+
* @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
|
|
374
|
+
* @example
|
|
375
|
+
* // 触发元素a.xx的blur事件
|
|
376
|
+
* DOMUtils.blur(document.querySelector("a.xx"))
|
|
377
|
+
* DOMUtils.blur("a.xx")
|
|
378
|
+
* DOMUtils.blur("a.xx",function(){
|
|
379
|
+
* console.log("触发blur事件成功")
|
|
380
|
+
* })
|
|
381
|
+
* */
|
|
382
|
+
blur(
|
|
383
|
+
element: HTMLElement | string | Window,
|
|
384
|
+
handler?: (event: Event) => void,
|
|
385
|
+
details?: object,
|
|
386
|
+
useDispatchToTriggerEvent?: boolean
|
|
387
|
+
) {
|
|
388
|
+
let DOMUtilsContext = this;
|
|
389
|
+
if (typeof element === "string") {
|
|
390
|
+
element = document.querySelector(element) as HTMLElement;
|
|
391
|
+
}
|
|
392
|
+
if (element == null) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (handler === null) {
|
|
396
|
+
DOMUtilsContext.trigger(
|
|
397
|
+
element,
|
|
398
|
+
"blur",
|
|
399
|
+
details,
|
|
400
|
+
useDispatchToTriggerEvent
|
|
401
|
+
);
|
|
402
|
+
} else {
|
|
403
|
+
DOMUtilsContext.on(
|
|
404
|
+
element,
|
|
405
|
+
"blur",
|
|
406
|
+
null,
|
|
407
|
+
handler as (event: Event) => void
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* 绑定或触发元素的focus事件
|
|
413
|
+
* @param element 目标元素
|
|
414
|
+
* @param handler (可选)事件处理函数
|
|
415
|
+
* @param details (可选)赋予触发的Event的额外属性
|
|
416
|
+
* @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
|
|
417
|
+
* @example
|
|
418
|
+
* // 触发元素a.xx的focus事件
|
|
419
|
+
* DOMUtils.focus(document.querySelector("a.xx"))
|
|
420
|
+
* DOMUtils.focus("a.xx")
|
|
421
|
+
* DOMUtils.focus("a.xx",function(){
|
|
422
|
+
* console.log("触发focus事件成功")
|
|
423
|
+
* })
|
|
424
|
+
* */
|
|
425
|
+
focus(
|
|
426
|
+
element: HTMLElement | string | Window,
|
|
427
|
+
handler?: (event: Event) => void,
|
|
428
|
+
details?: object,
|
|
429
|
+
useDispatchToTriggerEvent?: boolean
|
|
430
|
+
) {
|
|
431
|
+
let DOMUtilsContext = this;
|
|
432
|
+
if (typeof element === "string") {
|
|
433
|
+
element = document.querySelector(element) as HTMLElement;
|
|
434
|
+
}
|
|
435
|
+
if (element == null) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (handler == null) {
|
|
439
|
+
DOMUtilsContext.trigger(
|
|
440
|
+
element,
|
|
441
|
+
"focus",
|
|
442
|
+
details,
|
|
443
|
+
useDispatchToTriggerEvent
|
|
444
|
+
);
|
|
445
|
+
} else {
|
|
446
|
+
DOMUtilsContext.on(element, "focus", null, handler);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* 获取移动元素的transform偏移
|
|
451
|
+
*/
|
|
452
|
+
getTransform(
|
|
453
|
+
element: HTMLElement,
|
|
454
|
+
isShow: boolean = false
|
|
455
|
+
): {
|
|
456
|
+
transformLeft: number;
|
|
457
|
+
transformTop: number;
|
|
458
|
+
} {
|
|
459
|
+
let DOMUtilsContext = this;
|
|
460
|
+
let transform_left = 0;
|
|
461
|
+
let transform_top = 0;
|
|
462
|
+
if (!(isShow || (!isShow && CommonDOMUtils.isShow(element)))) {
|
|
463
|
+
/* 未显示 */
|
|
464
|
+
let { recovery } = CommonDOMUtils.showElement(element);
|
|
465
|
+
let transformInfo = DOMUtilsContext.getTransform(element, true);
|
|
466
|
+
recovery();
|
|
467
|
+
return transformInfo;
|
|
468
|
+
}
|
|
469
|
+
let elementTransform = getComputedStyle(element).transform;
|
|
470
|
+
if (
|
|
471
|
+
elementTransform != null &&
|
|
472
|
+
elementTransform !== "none" &&
|
|
473
|
+
elementTransform !== ""
|
|
474
|
+
) {
|
|
475
|
+
let elementTransformSplit = elementTransform
|
|
476
|
+
.match(/\((.+)\)/)?.[1]
|
|
477
|
+
.split(",");
|
|
478
|
+
if (elementTransformSplit) {
|
|
479
|
+
transform_left = Math.abs(parseInt(elementTransformSplit[4]));
|
|
480
|
+
transform_top = Math.abs(parseInt(elementTransformSplit[5]));
|
|
481
|
+
} else {
|
|
482
|
+
transform_left = 0;
|
|
483
|
+
transform_top = 0;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
transformLeft: transform_left,
|
|
488
|
+
transformTop: transform_top,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* 设置元素的value属性值
|
|
494
|
+
* @param element 目标元素
|
|
495
|
+
* @param value (可选)value属性值
|
|
496
|
+
* @returns 如果传入了value,则返回undefined;否则返回value属性值
|
|
497
|
+
* > true
|
|
498
|
+
* @example
|
|
499
|
+
* // 修改元素input.xx的复选框值为true
|
|
500
|
+
* DOMUtils.val(document.querySelector("input.xx"),true)
|
|
501
|
+
* DOMUtils.val("input.xx",true)
|
|
502
|
+
* */
|
|
503
|
+
val(element: HTMLInputElement | string, value: string | boolean): void;
|
|
504
|
+
/**
|
|
505
|
+
* 获取value属性值
|
|
506
|
+
* @param element 目标元素
|
|
507
|
+
* @example
|
|
508
|
+
* // 获取元素textarea的值
|
|
509
|
+
* DOMUtils.val(document.querySelector("textarea.xx"))
|
|
510
|
+
* */
|
|
511
|
+
val(element: HTMLInputElement | string): string;
|
|
512
|
+
/**
|
|
513
|
+
* 获取value属性值
|
|
514
|
+
* @param element 目标元素
|
|
515
|
+
* @example
|
|
516
|
+
* // 获取元素input.xx的复选框值
|
|
517
|
+
* DOMUtils.val(document.querySelector("input.xx"))
|
|
518
|
+
* DOMUtils.val("input.xx")
|
|
519
|
+
* */
|
|
520
|
+
val(element: HTMLInputElement): boolean | string;
|
|
521
|
+
val(element: HTMLInputElement | string, value?: string | boolean) {
|
|
522
|
+
if (typeof element === "string") {
|
|
523
|
+
element = document.querySelector(element) as HTMLInputElement;
|
|
524
|
+
}
|
|
525
|
+
if (element == null) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (value == null) {
|
|
529
|
+
if (
|
|
530
|
+
element.localName === "input" &&
|
|
531
|
+
(element.type === "checkbox" || element.type === "radio")
|
|
532
|
+
) {
|
|
533
|
+
return element.checked;
|
|
534
|
+
} else {
|
|
535
|
+
return element.value;
|
|
536
|
+
}
|
|
537
|
+
} else {
|
|
538
|
+
if (
|
|
539
|
+
element.localName === "input" &&
|
|
540
|
+
(element.type === "checkbox" || element.type === "radio")
|
|
541
|
+
) {
|
|
542
|
+
element.checked = !!value;
|
|
543
|
+
} else {
|
|
544
|
+
element.value = value as string;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* 获取元素的属性值
|
|
551
|
+
* @param element 目标元素
|
|
552
|
+
* @param propName 属性名
|
|
553
|
+
* @param propValue 属性值
|
|
554
|
+
* @example
|
|
555
|
+
* // 获取元素a.xx的属性data-value
|
|
556
|
+
* DOMUtils.val(document.querySelector("a.xx"),"data-value")
|
|
557
|
+
* DOMUtils.val("a.xx","data-value")
|
|
558
|
+
* > undefined
|
|
559
|
+
* */
|
|
560
|
+
prop<T extends any>(element: HTMLElement | string, propName: string): T;
|
|
561
|
+
/**
|
|
562
|
+
* 设置元素的属性值
|
|
563
|
+
* @param element 目标元素
|
|
564
|
+
* @param propName 属性名
|
|
565
|
+
* @param propValue 属性值
|
|
566
|
+
* @example
|
|
567
|
+
* // 设置元素a.xx的属性data-value为1
|
|
568
|
+
* DOMUtils.val(document.querySelector("a.xx"),"data-value",1)
|
|
569
|
+
* DOMUtils.val("a.xx","data-value",1)
|
|
570
|
+
* */
|
|
571
|
+
prop<T extends any>(
|
|
572
|
+
element: HTMLElement | string,
|
|
573
|
+
propName: string,
|
|
574
|
+
propValue: T
|
|
575
|
+
): void;
|
|
576
|
+
prop(element: HTMLElement | string, propName: string, propValue?: any) {
|
|
577
|
+
if (element == null) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (typeof element === "string") {
|
|
581
|
+
element = document.querySelector(element) as HTMLElement;
|
|
582
|
+
}
|
|
583
|
+
if (propValue == null) {
|
|
584
|
+
return (element as any)[propName];
|
|
585
|
+
} else {
|
|
586
|
+
(element as any)[propName] = propValue;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* 移除元素的属性
|
|
591
|
+
* @param element 目标元素
|
|
592
|
+
* @param attrName 属性名
|
|
593
|
+
* @example
|
|
594
|
+
* // 移除元素a.xx的属性data-value
|
|
595
|
+
* DOMUtils.removeAttr(document.querySelector("a.xx"),"data-value")
|
|
596
|
+
* DOMUtils.removeAttr("a.xx","data-value")
|
|
597
|
+
* */
|
|
598
|
+
removeAttr(element: HTMLElement | string, attrName: string) {
|
|
599
|
+
if (typeof element === "string") {
|
|
600
|
+
element = document.querySelector(element) as HTMLElement;
|
|
601
|
+
}
|
|
602
|
+
if (element == null) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
element.removeAttribute(attrName);
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* 移除元素class名
|
|
609
|
+
* @param element 目标元素
|
|
610
|
+
* @param className 类名
|
|
611
|
+
* @example
|
|
612
|
+
* // 移除元素a.xx的className为xx
|
|
613
|
+
* DOMUtils.removeClass(document.querySelector("a.xx"),"xx")
|
|
614
|
+
* DOMUtils.removeClass("a.xx","xx")
|
|
615
|
+
*/
|
|
616
|
+
removeClass(element: HTMLElement | string, className: string) {
|
|
617
|
+
if (typeof element === "string") {
|
|
618
|
+
element = document.querySelector(element) as HTMLElement;
|
|
619
|
+
}
|
|
620
|
+
if (element == null) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
if (className == null) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
element.classList.remove(className);
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* 移除元素的属性
|
|
630
|
+
* @param element 目标元素
|
|
631
|
+
* @param propName 属性名
|
|
632
|
+
* @example
|
|
633
|
+
* // 移除元素a.xx的href属性
|
|
634
|
+
* DOMUtils.removeProp(document.querySelector("a.xx"),"href")
|
|
635
|
+
* DOMUtils.removeProp("a.xx","href")
|
|
636
|
+
* */
|
|
637
|
+
removeProp(element: HTMLElement | string, propName: string) {
|
|
638
|
+
if (typeof element === "string") {
|
|
639
|
+
element = document.querySelector(element) as HTMLElement;
|
|
640
|
+
}
|
|
641
|
+
if (element == null) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
CommonDOMUtils.delete(element, propName);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* 将一个元素替换为另一个元素
|
|
648
|
+
* @param element 目标元素
|
|
649
|
+
* @param newElement 新元素
|
|
650
|
+
* @example
|
|
651
|
+
* // 替换元素a.xx为b.xx
|
|
652
|
+
* DOMUtils.replaceWith(document.querySelector("a.xx"),document.querySelector("b.xx"))
|
|
653
|
+
* DOMUtils.replaceWith("a.xx",'<b class="xx"></b>')
|
|
654
|
+
*/
|
|
655
|
+
replaceWith(
|
|
656
|
+
element: HTMLElement | string | NodeList | HTMLElement[] | Node,
|
|
657
|
+
newElement: HTMLElement | string | Node
|
|
658
|
+
) {
|
|
659
|
+
let DOMUtilsContext = this;
|
|
660
|
+
if (typeof element === "string") {
|
|
661
|
+
element = document.querySelector(element) as HTMLElement;
|
|
662
|
+
}
|
|
663
|
+
if (element == null) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
if (typeof newElement === "string") {
|
|
667
|
+
newElement = DOMUtilsContext.parseHTML(newElement, false, false);
|
|
668
|
+
}
|
|
669
|
+
if (element instanceof NodeList || element instanceof Array) {
|
|
670
|
+
element.forEach((item) => {
|
|
671
|
+
DOMUtilsContext.replaceWith(item, newElement);
|
|
672
|
+
});
|
|
673
|
+
} else {
|
|
674
|
+
element!.parentElement!.replaceChild(newElement as Node, element);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* 给元素添加class
|
|
679
|
+
* @param element 目标元素
|
|
680
|
+
* @param className class名
|
|
681
|
+
* @example
|
|
682
|
+
* // 元素a.xx的className添加_vue_
|
|
683
|
+
* DOMUtils.addClass(document.querySelector("a.xx"),"_vue_")
|
|
684
|
+
* DOMUtils.addClass("a.xx","_vue_")
|
|
685
|
+
* */
|
|
686
|
+
addClass(element: HTMLElement | string, className: string) {
|
|
687
|
+
if (typeof element === "string") {
|
|
688
|
+
element = document.querySelector(element) as HTMLElement;
|
|
689
|
+
}
|
|
690
|
+
if (element == null) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
element.classList.add(className);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* 函数在元素内部末尾添加子元素或HTML字符串
|
|
697
|
+
* @param element 目标元素
|
|
698
|
+
* @param content 子元素或HTML字符串
|
|
699
|
+
* @example
|
|
700
|
+
* // 元素a.xx的内部末尾添加一个元素
|
|
701
|
+
* DOMUtils.append(document.querySelector("a.xx"),document.querySelector("b.xx"))
|
|
702
|
+
* DOMUtils.append("a.xx","'<b class="xx"></b>")
|
|
703
|
+
* */
|
|
704
|
+
append(element: HTMLElement | string, content: HTMLElement | string) {
|
|
705
|
+
if (typeof element === "string") {
|
|
706
|
+
element = document.querySelector(element) as HTMLElement;
|
|
707
|
+
}
|
|
708
|
+
if (element == null) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
if (typeof content === "string") {
|
|
712
|
+
element.insertAdjacentHTML("beforeend", content);
|
|
713
|
+
} else {
|
|
714
|
+
element.appendChild(content);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* 函数 在元素内部开头添加子元素或HTML字符串
|
|
719
|
+
* @param element 目标元素
|
|
720
|
+
* @param content 子元素或HTML字符串
|
|
721
|
+
* @example
|
|
722
|
+
* // 元素a.xx内部开头添加一个元素
|
|
723
|
+
* DOMUtils.prepend(document.querySelector("a.xx"),document.querySelector("b.xx"))
|
|
724
|
+
* DOMUtils.prepend("a.xx","'<b class="xx"></b>")
|
|
725
|
+
* */
|
|
726
|
+
prepend(element: HTMLElement | string, content: HTMLElement | string) {
|
|
727
|
+
if (typeof element === "string") {
|
|
728
|
+
element = document.querySelector(element) as HTMLElement;
|
|
729
|
+
}
|
|
730
|
+
if (element == null) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (typeof content === "string") {
|
|
734
|
+
element.insertAdjacentHTML("afterbegin", content);
|
|
735
|
+
} else {
|
|
736
|
+
element.insertBefore(content, element.firstChild);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* 在元素后面添加兄弟元素或HTML字符串
|
|
741
|
+
* @param element 目标元素
|
|
742
|
+
* @param content 兄弟元素或HTML字符串
|
|
743
|
+
* @example
|
|
744
|
+
* // 元素a.xx后面添加一个元素
|
|
745
|
+
* DOMUtils.after(document.querySelector("a.xx"),document.querySelector("b.xx"))
|
|
746
|
+
* DOMUtils.after("a.xx","'<b class="xx"></b>")
|
|
747
|
+
* */
|
|
748
|
+
after(element: HTMLElement | string, content: HTMLElement | string) {
|
|
749
|
+
if (typeof element === "string") {
|
|
750
|
+
element = document.querySelector(element) as HTMLElement;
|
|
751
|
+
}
|
|
752
|
+
if (element == null) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (typeof content === "string") {
|
|
756
|
+
element.insertAdjacentHTML("afterend", content);
|
|
757
|
+
} else {
|
|
758
|
+
element!.parentElement!.insertBefore(content, element.nextSibling);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* 在元素前面添加兄弟元素或HTML字符串
|
|
763
|
+
* @param element 目标元素
|
|
764
|
+
* @param content 兄弟元素或HTML字符串
|
|
765
|
+
* @example
|
|
766
|
+
* // 元素a.xx前面添加一个元素
|
|
767
|
+
* DOMUtils.before(document.querySelector("a.xx"),document.querySelector("b.xx"))
|
|
768
|
+
* DOMUtils.before("a.xx","'<b class="xx"></b>")
|
|
769
|
+
* */
|
|
770
|
+
before(element: HTMLElement | string, content: HTMLElement | string) {
|
|
771
|
+
if (typeof element === "string") {
|
|
772
|
+
element = document.querySelector(element) as HTMLElement;
|
|
773
|
+
}
|
|
774
|
+
if (element == null) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
if (typeof content === "string") {
|
|
778
|
+
element.insertAdjacentHTML("beforebegin", content);
|
|
779
|
+
} else {
|
|
780
|
+
element!.parentElement!.insertBefore(content, element);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* 移除元素
|
|
785
|
+
* @param target 目标元素
|
|
786
|
+
* @example
|
|
787
|
+
* // 元素a.xx前面添加一个元素
|
|
788
|
+
* DOMUtils.remove(document.querySelector("a.xx"))
|
|
789
|
+
* DOMUtils.remove(document.querySelectorAll("a.xx"))
|
|
790
|
+
* DOMUtils.remove("a.xx")
|
|
791
|
+
* */
|
|
792
|
+
remove(target: HTMLElement | string | NodeList | HTMLElement[]) {
|
|
793
|
+
let DOMUtilsContext = this;
|
|
794
|
+
if (typeof target === "string") {
|
|
795
|
+
target = document.querySelectorAll(target) as NodeListOf<HTMLElement>;
|
|
796
|
+
}
|
|
797
|
+
if (target == null) {
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
if (target instanceof NodeList || target instanceof Array) {
|
|
801
|
+
target = target as HTMLElement[];
|
|
802
|
+
for (const element of target) {
|
|
803
|
+
DOMUtilsContext.remove(element);
|
|
804
|
+
}
|
|
805
|
+
} else {
|
|
806
|
+
target.remove();
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* 移除元素的所有子元素
|
|
811
|
+
* @param element 目标元素
|
|
812
|
+
* @example
|
|
813
|
+
* // 移除元素a.xx元素的所有子元素
|
|
814
|
+
* DOMUtils.empty(document.querySelector("a.xx"))
|
|
815
|
+
* DOMUtils.empty("a.xx")
|
|
816
|
+
* */
|
|
817
|
+
empty(element: HTMLElement | string) {
|
|
818
|
+
if (typeof element === "string") {
|
|
819
|
+
element = document.querySelector(element) as HTMLElement;
|
|
820
|
+
}
|
|
821
|
+
if (element == null) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
element.innerHTML = "";
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* 绑定事件
|
|
828
|
+
* @param element 需要绑定的元素|元素数组|window
|
|
829
|
+
* @param eventType 需要监听的事件
|
|
830
|
+
* @param callback 绑定事件触发的回调函数
|
|
831
|
+
* @param option
|
|
832
|
+
* + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
|
|
833
|
+
* + once 表示事件是否只触发一次。默认为false
|
|
834
|
+
* + passive 表示事件监听器是否不会调用preventDefault()。默认为false
|
|
835
|
+
* @example
|
|
836
|
+
* // 监听元素a.xx的click事件
|
|
837
|
+
* DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
|
|
838
|
+
* console.log("事件触发",event)
|
|
839
|
+
* })
|
|
840
|
+
* DOMUtils.on("a.xx","click",(event)=>{
|
|
841
|
+
* console.log("事件触发",event)
|
|
842
|
+
* })
|
|
843
|
+
*/
|
|
844
|
+
on<T extends Event>(
|
|
845
|
+
element:
|
|
846
|
+
| HTMLElement
|
|
847
|
+
| string
|
|
848
|
+
| NodeList
|
|
849
|
+
| HTMLElement[]
|
|
850
|
+
| Window
|
|
851
|
+
| Document
|
|
852
|
+
| Element
|
|
853
|
+
| null
|
|
854
|
+
| typeof globalThis,
|
|
855
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[],
|
|
856
|
+
callback: (event: T) => void,
|
|
857
|
+
option?: boolean | AddEventListenerOptions
|
|
858
|
+
): void;
|
|
859
|
+
/**
|
|
860
|
+
* 绑定事件
|
|
861
|
+
* @param element 需要绑定的元素|元素数组|window
|
|
862
|
+
* @param eventType 需要监听的事件
|
|
863
|
+
* @param callback 绑定事件触发的回调函数
|
|
864
|
+
* @param option
|
|
865
|
+
* + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
|
|
866
|
+
* + once 表示事件是否只触发一次。默认为false
|
|
867
|
+
* + passive 表示事件监听器是否不会调用preventDefault()。默认为false
|
|
868
|
+
* @example
|
|
869
|
+
* // 监听元素a.xx的click事件
|
|
870
|
+
* DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
|
|
871
|
+
* console.log("事件触发",event)
|
|
872
|
+
* })
|
|
873
|
+
* DOMUtils.on("a.xx","click",(event)=>{
|
|
874
|
+
* console.log("事件触发",event)
|
|
875
|
+
* })
|
|
876
|
+
*/
|
|
877
|
+
on<T extends Event>(
|
|
878
|
+
element:
|
|
879
|
+
| HTMLElement
|
|
880
|
+
| string
|
|
881
|
+
| NodeList
|
|
882
|
+
| HTMLElement[]
|
|
883
|
+
| Window
|
|
884
|
+
| Document
|
|
885
|
+
| Element
|
|
886
|
+
| null
|
|
887
|
+
| typeof globalThis,
|
|
888
|
+
eventType: string,
|
|
889
|
+
callback: (event: T) => void,
|
|
890
|
+
option?: boolean | AddEventListenerOptions
|
|
891
|
+
): void;
|
|
892
|
+
/**
|
|
893
|
+
* 绑定事件
|
|
894
|
+
* @param element 需要绑定的元素|元素数组|window
|
|
895
|
+
* @param eventType 需要监听的事件
|
|
896
|
+
* @param selector 子元素选择器
|
|
897
|
+
* @param callback 绑定事件触发的回调函数
|
|
898
|
+
* @param option
|
|
899
|
+
* + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
|
|
900
|
+
* + once 表示事件是否只触发一次。默认为false
|
|
901
|
+
* + passive 表示事件监听器是否不会调用preventDefault()。默认为false
|
|
902
|
+
* @example
|
|
903
|
+
* // 监听元素a.xx的click、tap、hover事件
|
|
904
|
+
* DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event)=>{
|
|
905
|
+
* console.log("事件触发",event)
|
|
906
|
+
* })
|
|
907
|
+
* DOMUtils.on("a.xx",["click","tap","hover"],(event)=>{
|
|
908
|
+
* console.log("事件触发",event)
|
|
909
|
+
* })
|
|
910
|
+
* @example
|
|
911
|
+
* // 监听全局document下的子元素a.xx的click事件
|
|
912
|
+
* DOMUtils.on(document,"click tap hover","a.xx",(event)=>{
|
|
913
|
+
* console.log("事件触发",event)
|
|
914
|
+
* })
|
|
915
|
+
*/
|
|
916
|
+
on<T extends Event>(
|
|
917
|
+
element:
|
|
918
|
+
| HTMLElement
|
|
919
|
+
| string
|
|
920
|
+
| NodeList
|
|
921
|
+
| HTMLElement[]
|
|
922
|
+
| Window
|
|
923
|
+
| Document
|
|
924
|
+
| Element
|
|
925
|
+
| null
|
|
926
|
+
| typeof globalThis,
|
|
927
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[],
|
|
928
|
+
selector: string | undefined | null,
|
|
929
|
+
callback: (event: T) => void,
|
|
930
|
+
option?: boolean | AddEventListenerOptions
|
|
931
|
+
): void;
|
|
932
|
+
/**
|
|
933
|
+
* 绑定事件
|
|
934
|
+
* @param element 需要绑定的元素|元素数组|window
|
|
935
|
+
* @param eventType 需要监听的事件
|
|
936
|
+
* @param selector 子元素选择器
|
|
937
|
+
* @param callback 绑定事件触发的回调函数
|
|
938
|
+
* @param option
|
|
939
|
+
* + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
|
|
940
|
+
* + once 表示事件是否只触发一次。默认为false
|
|
941
|
+
* + passive 表示事件监听器是否不会调用preventDefault()。默认为false
|
|
942
|
+
* @example
|
|
943
|
+
* // 监听元素a.xx的click、tap、hover事件
|
|
944
|
+
* DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event)=>{
|
|
945
|
+
* console.log("事件触发",event)
|
|
946
|
+
* })
|
|
947
|
+
* DOMUtils.on("a.xx",["click","tap","hover"],(event)=>{
|
|
948
|
+
* console.log("事件触发",event)
|
|
949
|
+
* })
|
|
950
|
+
* @example
|
|
951
|
+
* // 监听全局document下的子元素a.xx的click事件
|
|
952
|
+
* DOMUtils.on(document,"click tap hover","a.xx",(event)=>{
|
|
953
|
+
* console.log("事件触发",event)
|
|
954
|
+
* })
|
|
955
|
+
*/
|
|
956
|
+
on<T extends Event>(
|
|
957
|
+
element:
|
|
958
|
+
| HTMLElement
|
|
959
|
+
| string
|
|
960
|
+
| NodeList
|
|
961
|
+
| HTMLElement[]
|
|
962
|
+
| Window
|
|
963
|
+
| Document
|
|
964
|
+
| Element
|
|
965
|
+
| null
|
|
966
|
+
| typeof globalThis,
|
|
967
|
+
eventType: string,
|
|
968
|
+
selector: string | undefined | null,
|
|
969
|
+
callback: (event: T) => void,
|
|
970
|
+
option?: boolean | AddEventListenerOptions
|
|
971
|
+
): void;
|
|
972
|
+
on<T extends Event>(
|
|
973
|
+
element:
|
|
974
|
+
| HTMLElement
|
|
975
|
+
| string
|
|
976
|
+
| NodeList
|
|
977
|
+
| HTMLElement[]
|
|
978
|
+
| Window
|
|
979
|
+
| Document
|
|
980
|
+
| Element
|
|
981
|
+
| null
|
|
982
|
+
| typeof globalThis,
|
|
983
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
|
|
984
|
+
selector: string | undefined | ((event: T) => void) | null,
|
|
985
|
+
callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
|
|
986
|
+
option?: boolean | AddEventListenerOptions
|
|
987
|
+
) {
|
|
988
|
+
/**
|
|
989
|
+
* 获取option配置
|
|
990
|
+
* @param args
|
|
991
|
+
* @param startIndex
|
|
992
|
+
* @param option
|
|
993
|
+
*/
|
|
994
|
+
function getOption(
|
|
995
|
+
args: IArguments,
|
|
996
|
+
startIndex: number,
|
|
997
|
+
option: AddEventListenerOptions
|
|
998
|
+
) {
|
|
999
|
+
if (typeof args[startIndex] === "boolean") {
|
|
1000
|
+
option.capture = args[startIndex];
|
|
1001
|
+
if (typeof args[startIndex + 1] === "boolean") {
|
|
1002
|
+
option.once = args[startIndex + 1];
|
|
1003
|
+
}
|
|
1004
|
+
if (typeof args[startIndex + 2] === "boolean") {
|
|
1005
|
+
option.passive = args[startIndex + 2];
|
|
1006
|
+
}
|
|
1007
|
+
} else if (
|
|
1008
|
+
typeof args[startIndex] === "object" &&
|
|
1009
|
+
("capture" in args[startIndex] ||
|
|
1010
|
+
"once" in args[startIndex] ||
|
|
1011
|
+
"passive" in args[startIndex])
|
|
1012
|
+
) {
|
|
1013
|
+
option.capture = args[startIndex].capture;
|
|
1014
|
+
option.once = args[startIndex].once;
|
|
1015
|
+
option.passive = args[startIndex].passive;
|
|
1016
|
+
}
|
|
1017
|
+
return option;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
let DOMUtilsContext = this;
|
|
1021
|
+
let args = arguments;
|
|
1022
|
+
if (typeof element === "string") {
|
|
1023
|
+
element = document.querySelectorAll(element);
|
|
1024
|
+
}
|
|
1025
|
+
if (element == null) {
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
let elementList: HTMLElement[] = [];
|
|
1029
|
+
if (element instanceof NodeList || Array.isArray(element)) {
|
|
1030
|
+
element = element as HTMLElement[];
|
|
1031
|
+
elementList = [...element];
|
|
1032
|
+
} else {
|
|
1033
|
+
elementList.push(element as HTMLElement);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
let eventTypeList: string[] = [];
|
|
1037
|
+
if (Array.isArray(eventType)) {
|
|
1038
|
+
eventTypeList = eventTypeList.concat(eventType as string[]);
|
|
1039
|
+
} else if (typeof eventType === "string") {
|
|
1040
|
+
eventTypeList = eventTypeList.concat(eventType.split(" "));
|
|
1041
|
+
}
|
|
1042
|
+
let _selector_: string | undefined = selector as any;
|
|
1043
|
+
let _callback_: (event: T) => void = callback as any;
|
|
1044
|
+
let _option_: AddEventListenerOptions = {
|
|
1045
|
+
capture: false,
|
|
1046
|
+
once: false,
|
|
1047
|
+
passive: false,
|
|
1048
|
+
};
|
|
1049
|
+
if (typeof selector === "function") {
|
|
1050
|
+
/* 这是为没有selector的情况 */
|
|
1051
|
+
_selector_ = void 0;
|
|
1052
|
+
_callback_ = selector;
|
|
1053
|
+
_option_ = getOption(args, 3, _option_);
|
|
1054
|
+
} else {
|
|
1055
|
+
/* 这是存在selector的情况 */
|
|
1056
|
+
_option_ = getOption(args, 4, _option_);
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* 如果是once,那么删除该监听和元素上的事件和监听
|
|
1060
|
+
*/
|
|
1061
|
+
function checkOptionOnceToRemoveEventListener() {
|
|
1062
|
+
if (_option_.once) {
|
|
1063
|
+
DOMUtilsContext.off(
|
|
1064
|
+
element,
|
|
1065
|
+
eventType as any,
|
|
1066
|
+
selector as any,
|
|
1067
|
+
callback as any,
|
|
1068
|
+
option
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
elementList.forEach((elementItem) => {
|
|
1073
|
+
function ownCallBack(event: Event) {
|
|
1074
|
+
let target = event.target as HTMLElement;
|
|
1075
|
+
if (_selector_) {
|
|
1076
|
+
/* 存在自定义子元素选择器 */
|
|
1077
|
+
let totalParent = CommonDOMUtils.isWin(elementItem)
|
|
1078
|
+
? document.documentElement
|
|
1079
|
+
: elementItem;
|
|
1080
|
+
if (target.matches(_selector_)) {
|
|
1081
|
+
/* 当前目标可以被selector所匹配到 */
|
|
1082
|
+
_callback_.call(target, event as any);
|
|
1083
|
+
checkOptionOnceToRemoveEventListener();
|
|
1084
|
+
} else if (
|
|
1085
|
+
target.closest(_selector_) &&
|
|
1086
|
+
totalParent.contains(target.closest(_selector_))
|
|
1087
|
+
) {
|
|
1088
|
+
/* 在上层与主元素之间寻找可以被selector所匹配到的 */
|
|
1089
|
+
let closestElement = target.closest(_selector_);
|
|
1090
|
+
/* event的target值不能直接修改 */
|
|
1091
|
+
OriginPrototype.Object.defineProperty(event, "target", {
|
|
1092
|
+
get() {
|
|
1093
|
+
return closestElement;
|
|
1094
|
+
},
|
|
1095
|
+
});
|
|
1096
|
+
_callback_.call(closestElement, event as any);
|
|
1097
|
+
checkOptionOnceToRemoveEventListener();
|
|
1098
|
+
}
|
|
1099
|
+
} else {
|
|
1100
|
+
_callback_.call(elementItem, event as any);
|
|
1101
|
+
checkOptionOnceToRemoveEventListener();
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/* 遍历事件名设置元素事件 */
|
|
1106
|
+
eventTypeList.forEach((eventName) => {
|
|
1107
|
+
elementItem.addEventListener(eventName, ownCallBack, _option_);
|
|
1108
|
+
|
|
1109
|
+
if (_callback_ && (_callback_ as any).delegate) {
|
|
1110
|
+
elementItem.setAttribute("data-delegate", _selector_ as string);
|
|
1111
|
+
}
|
|
1112
|
+
/* 获取对象上的事件 */
|
|
1113
|
+
let elementEvents =
|
|
1114
|
+
(elementItem as any)[DOMUtilsData.SymbolEvents] || {};
|
|
1115
|
+
/* 初始化对象上的xx事件 */
|
|
1116
|
+
elementEvents[eventName] = elementEvents[eventName] || [];
|
|
1117
|
+
elementEvents[eventName].push({
|
|
1118
|
+
selector: _selector_,
|
|
1119
|
+
option: _option_,
|
|
1120
|
+
callback: ownCallBack,
|
|
1121
|
+
originCallBack: _callback_,
|
|
1122
|
+
});
|
|
1123
|
+
/* 覆盖事件 */
|
|
1124
|
+
(elementItem as any)[DOMUtilsData.SymbolEvents] = elementEvents;
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* 取消绑定事件
|
|
1131
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1132
|
+
* @param eventType 需要取消监听的事件
|
|
1133
|
+
* @param callback 通过DOMUtils.on绑定的事件函数
|
|
1134
|
+
* @param option
|
|
1135
|
+
* + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
|
|
1136
|
+
* @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
|
|
1137
|
+
* @example
|
|
1138
|
+
* // 取消监听元素a.xx的click事件
|
|
1139
|
+
* DOMUtils.off(document.querySelector("a.xx"),"click")
|
|
1140
|
+
* DOMUtils.off("a.xx","click")
|
|
1141
|
+
*/
|
|
1142
|
+
off<T extends Event>(
|
|
1143
|
+
element:
|
|
1144
|
+
| HTMLElement
|
|
1145
|
+
| string
|
|
1146
|
+
| NodeList
|
|
1147
|
+
| HTMLElement[]
|
|
1148
|
+
| Window
|
|
1149
|
+
| Document
|
|
1150
|
+
| Element
|
|
1151
|
+
| null
|
|
1152
|
+
| typeof globalThis,
|
|
1153
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[],
|
|
1154
|
+
callback?: (event: T) => void,
|
|
1155
|
+
option?: boolean | AddEventListenerOptions,
|
|
1156
|
+
filter?: (
|
|
1157
|
+
value: DOMUtilsEventListenerOptionsAttribute,
|
|
1158
|
+
index: number,
|
|
1159
|
+
array: DOMUtilsEventListenerOptionsAttribute[]
|
|
1160
|
+
) => boolean
|
|
1161
|
+
): void;
|
|
1162
|
+
/**
|
|
1163
|
+
* 取消绑定事件
|
|
1164
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1165
|
+
* @param eventType 需要取消监听的事件
|
|
1166
|
+
* @param callback 通过DOMUtils.on绑定的事件函数
|
|
1167
|
+
* @param option
|
|
1168
|
+
* + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
|
|
1169
|
+
* @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
|
|
1170
|
+
* @example
|
|
1171
|
+
* // 取消监听元素a.xx的click事件
|
|
1172
|
+
* DOMUtils.off(document.querySelector("a.xx"),"click")
|
|
1173
|
+
* DOMUtils.off("a.xx","click")
|
|
1174
|
+
*/
|
|
1175
|
+
off<T extends Event>(
|
|
1176
|
+
element:
|
|
1177
|
+
| HTMLElement
|
|
1178
|
+
| string
|
|
1179
|
+
| NodeList
|
|
1180
|
+
| HTMLElement[]
|
|
1181
|
+
| Window
|
|
1182
|
+
| Document
|
|
1183
|
+
| Element
|
|
1184
|
+
| null
|
|
1185
|
+
| typeof globalThis,
|
|
1186
|
+
eventType: string,
|
|
1187
|
+
callback?: (event: T) => void,
|
|
1188
|
+
option?: boolean | AddEventListenerOptions,
|
|
1189
|
+
filter?: (
|
|
1190
|
+
value: DOMUtilsEventListenerOptionsAttribute,
|
|
1191
|
+
index: number,
|
|
1192
|
+
array: DOMUtilsEventListenerOptionsAttribute[]
|
|
1193
|
+
) => boolean
|
|
1194
|
+
): void;
|
|
1195
|
+
/**
|
|
1196
|
+
* 取消绑定事件
|
|
1197
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1198
|
+
* @param eventType 需要取消监听的事件
|
|
1199
|
+
* @param selector 子元素选择器
|
|
1200
|
+
* @param callback 通过DOMUtils.on绑定的事件函数
|
|
1201
|
+
* @param option
|
|
1202
|
+
* + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
|
|
1203
|
+
* @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
|
|
1204
|
+
* @example
|
|
1205
|
+
* // 取消监听元素a.xx的click、tap、hover事件
|
|
1206
|
+
* DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
|
|
1207
|
+
* DOMUtils.off("a.xx",["click","tap","hover"])
|
|
1208
|
+
*/
|
|
1209
|
+
off<T extends Event>(
|
|
1210
|
+
element:
|
|
1211
|
+
| HTMLElement
|
|
1212
|
+
| string
|
|
1213
|
+
| NodeList
|
|
1214
|
+
| HTMLElement[]
|
|
1215
|
+
| Window
|
|
1216
|
+
| Document
|
|
1217
|
+
| Element
|
|
1218
|
+
| null
|
|
1219
|
+
| typeof globalThis,
|
|
1220
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[],
|
|
1221
|
+
selector?: string | undefined,
|
|
1222
|
+
callback?: (event: T) => void,
|
|
1223
|
+
option?: boolean | AddEventListenerOptions,
|
|
1224
|
+
filter?: (
|
|
1225
|
+
value: DOMUtilsEventListenerOptionsAttribute,
|
|
1226
|
+
index: number,
|
|
1227
|
+
array: DOMUtilsEventListenerOptionsAttribute[]
|
|
1228
|
+
) => boolean
|
|
1229
|
+
): void;
|
|
1230
|
+
/**
|
|
1231
|
+
* 取消绑定事件
|
|
1232
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1233
|
+
* @param eventType 需要取消监听的事件
|
|
1234
|
+
* @param selector 子元素选择器
|
|
1235
|
+
* @param callback 通过DOMUtils.on绑定的事件函数
|
|
1236
|
+
* @param option
|
|
1237
|
+
* + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
|
|
1238
|
+
* @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
|
|
1239
|
+
* @example
|
|
1240
|
+
* // 取消监听元素a.xx的click、tap、hover事件
|
|
1241
|
+
* DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
|
|
1242
|
+
* DOMUtils.off("a.xx",["click","tap","hover"])
|
|
1243
|
+
*/
|
|
1244
|
+
off<T extends Event>(
|
|
1245
|
+
element:
|
|
1246
|
+
| HTMLElement
|
|
1247
|
+
| string
|
|
1248
|
+
| NodeList
|
|
1249
|
+
| HTMLElement[]
|
|
1250
|
+
| Window
|
|
1251
|
+
| Document
|
|
1252
|
+
| Element
|
|
1253
|
+
| null
|
|
1254
|
+
| typeof globalThis,
|
|
1255
|
+
eventType: string,
|
|
1256
|
+
selector?: string | undefined,
|
|
1257
|
+
callback?: (event: T) => void,
|
|
1258
|
+
option?: boolean | AddEventListenerOptions,
|
|
1259
|
+
filter?: (
|
|
1260
|
+
value: DOMUtilsEventListenerOptionsAttribute,
|
|
1261
|
+
index: number,
|
|
1262
|
+
array: DOMUtilsEventListenerOptionsAttribute[]
|
|
1263
|
+
) => boolean
|
|
1264
|
+
): void;
|
|
1265
|
+
off<T extends Event>(
|
|
1266
|
+
element:
|
|
1267
|
+
| HTMLElement
|
|
1268
|
+
| string
|
|
1269
|
+
| NodeList
|
|
1270
|
+
| HTMLElement[]
|
|
1271
|
+
| Window
|
|
1272
|
+
| Document
|
|
1273
|
+
| Element
|
|
1274
|
+
| null
|
|
1275
|
+
| typeof globalThis,
|
|
1276
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
|
|
1277
|
+
selector?: string | undefined | ((event: T) => void),
|
|
1278
|
+
callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
|
|
1279
|
+
option?:
|
|
1280
|
+
| boolean
|
|
1281
|
+
| AddEventListenerOptions
|
|
1282
|
+
| ((
|
|
1283
|
+
value: DOMUtilsEventListenerOptionsAttribute,
|
|
1284
|
+
index: number,
|
|
1285
|
+
array: DOMUtilsEventListenerOptionsAttribute[]
|
|
1286
|
+
) => boolean),
|
|
1287
|
+
filter?: (
|
|
1288
|
+
value: DOMUtilsEventListenerOptionsAttribute,
|
|
1289
|
+
index: number,
|
|
1290
|
+
array: DOMUtilsEventListenerOptionsAttribute[]
|
|
1291
|
+
) => boolean
|
|
1292
|
+
) {
|
|
1293
|
+
/**
|
|
1294
|
+
* 获取option配置
|
|
1295
|
+
* @param args1
|
|
1296
|
+
* @param startIndex
|
|
1297
|
+
* @param option
|
|
1298
|
+
*/
|
|
1299
|
+
function getOption(
|
|
1300
|
+
args1: IArguments,
|
|
1301
|
+
startIndex: number,
|
|
1302
|
+
option: EventListenerOptions
|
|
1303
|
+
) {
|
|
1304
|
+
if (typeof args1[startIndex] === "boolean") {
|
|
1305
|
+
option.capture = args1[startIndex];
|
|
1306
|
+
} else if (
|
|
1307
|
+
typeof args1[startIndex] === "object" &&
|
|
1308
|
+
"capture" in args1[startIndex]
|
|
1309
|
+
) {
|
|
1310
|
+
option.capture = args1[startIndex].capture;
|
|
1311
|
+
}
|
|
1312
|
+
return option;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
let args = arguments;
|
|
1316
|
+
if (typeof element === "string") {
|
|
1317
|
+
element = document.querySelectorAll(element);
|
|
1318
|
+
}
|
|
1319
|
+
if (element == null) {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
let elementList: HTMLElement[] = [];
|
|
1323
|
+
if (element instanceof NodeList || Array.isArray(element)) {
|
|
1324
|
+
element = element as HTMLElement[];
|
|
1325
|
+
elementList = [...element];
|
|
1326
|
+
} else {
|
|
1327
|
+
elementList.push(element as HTMLElement);
|
|
1328
|
+
}
|
|
1329
|
+
let eventTypeList: string[] = [];
|
|
1330
|
+
if (Array.isArray(eventType)) {
|
|
1331
|
+
eventTypeList = eventTypeList.concat(eventType as string[]);
|
|
1332
|
+
} else if (typeof eventType === "string") {
|
|
1333
|
+
eventTypeList = eventTypeList.concat(eventType.split(" "));
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* 子元素选择器
|
|
1337
|
+
*/
|
|
1338
|
+
let _selector_: string | undefined = selector as any;
|
|
1339
|
+
/**
|
|
1340
|
+
* 事件的回调函数
|
|
1341
|
+
*/
|
|
1342
|
+
let _callback_: (event: T) => void = callback as any;
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* 事件的配置
|
|
1346
|
+
*/
|
|
1347
|
+
let _option_: EventListenerOptions = {
|
|
1348
|
+
capture: false,
|
|
1349
|
+
};
|
|
1350
|
+
if (typeof selector === "function") {
|
|
1351
|
+
/* 这是为没有selector的情况 */
|
|
1352
|
+
_selector_ = void 0;
|
|
1353
|
+
_callback_ = selector;
|
|
1354
|
+
_option_ = getOption(args, 3, _option_);
|
|
1355
|
+
} else {
|
|
1356
|
+
_option_ = getOption(args, 4, _option_);
|
|
1357
|
+
}
|
|
1358
|
+
elementList.forEach((elementItem) => {
|
|
1359
|
+
/* 获取对象上的事件 */
|
|
1360
|
+
let elementEvents = (elementItem as any)[DOMUtilsData.SymbolEvents] || {};
|
|
1361
|
+
eventTypeList.forEach((eventName) => {
|
|
1362
|
+
let handlers: DOMUtilsEventListenerOptionsAttribute[] =
|
|
1363
|
+
elementEvents[eventName] || [];
|
|
1364
|
+
if (typeof filter === "function") {
|
|
1365
|
+
handlers = handlers.filter(filter);
|
|
1366
|
+
}
|
|
1367
|
+
for (let index = 0; index < handlers.length; index++) {
|
|
1368
|
+
let handler = handlers[index];
|
|
1369
|
+
let flag = false;
|
|
1370
|
+
if (!_selector_ || handler.selector === _selector_) {
|
|
1371
|
+
/* selector不为空,进行selector判断 */
|
|
1372
|
+
flag = true;
|
|
1373
|
+
}
|
|
1374
|
+
if (
|
|
1375
|
+
!_callback_ ||
|
|
1376
|
+
handler.callback === _callback_ ||
|
|
1377
|
+
handler.originCallBack === _callback_
|
|
1378
|
+
) {
|
|
1379
|
+
/* callback不为空,进行callback判断 */
|
|
1380
|
+
flag = true;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
if (flag) {
|
|
1384
|
+
elementItem.removeEventListener(
|
|
1385
|
+
eventName,
|
|
1386
|
+
handler.callback,
|
|
1387
|
+
_option_
|
|
1388
|
+
);
|
|
1389
|
+
handlers.splice(index--, 1);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
if (handlers.length === 0) {
|
|
1393
|
+
/* 如果没有任意的handler,那么删除该属性 */
|
|
1394
|
+
CommonDOMUtils.delete(elementEvents, eventType);
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
(elementItem as any)[DOMUtilsData.SymbolEvents] = elementEvents;
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
/**
|
|
1402
|
+
* 取消绑定所有的事件
|
|
1403
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1404
|
+
* @param eventType (可选)需要取消监听的事件
|
|
1405
|
+
*/
|
|
1406
|
+
offAll(
|
|
1407
|
+
element:
|
|
1408
|
+
| HTMLElement
|
|
1409
|
+
| string
|
|
1410
|
+
| NodeList
|
|
1411
|
+
| HTMLElement[]
|
|
1412
|
+
| Window
|
|
1413
|
+
| Element
|
|
1414
|
+
| null,
|
|
1415
|
+
eventType?: string
|
|
1416
|
+
): void;
|
|
1417
|
+
/**
|
|
1418
|
+
* 取消绑定所有的事件
|
|
1419
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1420
|
+
* @param eventType (可选)需要取消监听的事件
|
|
1421
|
+
*/
|
|
1422
|
+
offAll(
|
|
1423
|
+
element:
|
|
1424
|
+
| HTMLElement
|
|
1425
|
+
| string
|
|
1426
|
+
| NodeList
|
|
1427
|
+
| HTMLElement[]
|
|
1428
|
+
| Window
|
|
1429
|
+
| Element
|
|
1430
|
+
| null,
|
|
1431
|
+
eventType?: DOMUtils_EventType | DOMUtils_EventType[]
|
|
1432
|
+
): void;
|
|
1433
|
+
/**
|
|
1434
|
+
* 取消绑定所有的事件
|
|
1435
|
+
* @param element 需要取消绑定的元素|元素数组
|
|
1436
|
+
* @param eventType (可选)需要取消监听的事件
|
|
1437
|
+
*/
|
|
1438
|
+
offAll(
|
|
1439
|
+
element:
|
|
1440
|
+
| HTMLElement
|
|
1441
|
+
| string
|
|
1442
|
+
| NodeList
|
|
1443
|
+
| HTMLElement[]
|
|
1444
|
+
| Window
|
|
1445
|
+
| Element
|
|
1446
|
+
| null,
|
|
1447
|
+
eventType?: DOMUtils_EventType | DOMUtils_EventType[] | string
|
|
1448
|
+
) {
|
|
1449
|
+
if (typeof element === "string") {
|
|
1450
|
+
element = document.querySelectorAll(element);
|
|
1451
|
+
}
|
|
1452
|
+
if (element == null) {
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
let elementList: HTMLElement[] = [];
|
|
1456
|
+
if (element instanceof NodeList || Array.isArray(element)) {
|
|
1457
|
+
element = element as HTMLElement[];
|
|
1458
|
+
elementList = [...element];
|
|
1459
|
+
} else {
|
|
1460
|
+
elementList.push(element as HTMLElement);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
let eventTypeList: string[] = [];
|
|
1464
|
+
if (Array.isArray(eventType)) {
|
|
1465
|
+
eventTypeList = eventTypeList.concat(eventType as string[]);
|
|
1466
|
+
} else if (typeof eventType === "string") {
|
|
1467
|
+
eventTypeList = eventTypeList.concat(eventType.split(" "));
|
|
1468
|
+
}
|
|
1469
|
+
elementList.forEach((elementItem) => {
|
|
1470
|
+
Object.getOwnPropertySymbols(elementItem).forEach((symbolEvents) => {
|
|
1471
|
+
if (!symbolEvents.toString().startsWith("Symbol(events_")) {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
let elementEvents = (elementItem as any)[symbolEvents] || {};
|
|
1475
|
+
let iterEventNameList = eventTypeList.length
|
|
1476
|
+
? eventTypeList
|
|
1477
|
+
: Object.keys(elementEvents);
|
|
1478
|
+
iterEventNameList.forEach((eventName) => {
|
|
1479
|
+
let handlers = elementEvents[eventName];
|
|
1480
|
+
if (!handlers) {
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
for (const handler of handlers) {
|
|
1484
|
+
elementItem.removeEventListener(eventName, handler.callback, {
|
|
1485
|
+
capture: handler["option"]["capture"],
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
CommonDOMUtils.delete((elementItem as any)[symbolEvents], eventName);
|
|
1489
|
+
});
|
|
1490
|
+
});
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* 主动触发事件
|
|
1495
|
+
* @param element 需要触发的元素|元素数组|window
|
|
1496
|
+
* @param eventType 需要触发的事件
|
|
1497
|
+
* @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
|
|
1498
|
+
* @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
|
|
1499
|
+
* @example
|
|
1500
|
+
* // 触发元素a.xx的click事件
|
|
1501
|
+
* DOMUtils.trigger(document.querySelector("a.xx"),"click")
|
|
1502
|
+
* DOMUtils.trigger("a.xx","click")
|
|
1503
|
+
* // 触发元素a.xx的click、tap、hover事件
|
|
1504
|
+
* DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
|
|
1505
|
+
* DOMUtils.trigger("a.xx",["click","tap","hover"])
|
|
1506
|
+
*/
|
|
1507
|
+
trigger(
|
|
1508
|
+
element: HTMLElement | string | NodeList | any[] | Window | Document,
|
|
1509
|
+
eventType: string,
|
|
1510
|
+
details?: object,
|
|
1511
|
+
useDispatchToTriggerEvent?: boolean
|
|
1512
|
+
): void;
|
|
1513
|
+
/**
|
|
1514
|
+
* 主动触发事件
|
|
1515
|
+
* @param element 需要触发的元素|元素数组|window
|
|
1516
|
+
* @param eventType 需要触发的事件
|
|
1517
|
+
* @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
|
|
1518
|
+
* @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
|
|
1519
|
+
* @example
|
|
1520
|
+
* // 触发元素a.xx的click事件
|
|
1521
|
+
* DOMUtils.trigger(document.querySelector("a.xx"),"click")
|
|
1522
|
+
* DOMUtils.trigger("a.xx","click")
|
|
1523
|
+
* // 触发元素a.xx的click、tap、hover事件
|
|
1524
|
+
* DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
|
|
1525
|
+
* DOMUtils.trigger("a.xx",["click","tap","hover"])
|
|
1526
|
+
*/
|
|
1527
|
+
trigger(
|
|
1528
|
+
element: HTMLElement | string | NodeList | any[] | Window | Document,
|
|
1529
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[],
|
|
1530
|
+
details?: object,
|
|
1531
|
+
useDispatchToTriggerEvent?: boolean
|
|
1532
|
+
): void;
|
|
1533
|
+
/**
|
|
1534
|
+
* 主动触发事件
|
|
1535
|
+
* @param element 需要触发的元素|元素数组|window
|
|
1536
|
+
* @param eventType 需要触发的事件
|
|
1537
|
+
* @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
|
|
1538
|
+
* @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
|
|
1539
|
+
* @example
|
|
1540
|
+
* // 触发元素a.xx的click事件
|
|
1541
|
+
* DOMUtils.trigger(document.querySelector("a.xx"),"click")
|
|
1542
|
+
* DOMUtils.trigger("a.xx","click")
|
|
1543
|
+
* // 触发元素a.xx的click、tap、hover事件
|
|
1544
|
+
* DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
|
|
1545
|
+
* DOMUtils.trigger("a.xx",["click","tap","hover"])
|
|
1546
|
+
*/
|
|
1547
|
+
trigger(
|
|
1548
|
+
element: HTMLElement | string | NodeList | any[] | Window | Document,
|
|
1549
|
+
eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
|
|
1550
|
+
details?: object,
|
|
1551
|
+
useDispatchToTriggerEvent: boolean = true
|
|
1552
|
+
) {
|
|
1553
|
+
if (typeof element === "string") {
|
|
1554
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1555
|
+
}
|
|
1556
|
+
if (element == null) {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
let elementList = [];
|
|
1560
|
+
if (element instanceof NodeList || Array.isArray(element)) {
|
|
1561
|
+
element = element as HTMLElement[];
|
|
1562
|
+
elementList = [...element];
|
|
1563
|
+
} else {
|
|
1564
|
+
elementList = [element];
|
|
1565
|
+
}
|
|
1566
|
+
let eventTypeList: string[] = [];
|
|
1567
|
+
if (Array.isArray(eventType)) {
|
|
1568
|
+
eventTypeList = eventType as string[];
|
|
1569
|
+
} else if (typeof eventType === "string") {
|
|
1570
|
+
eventTypeList = eventType.split(" ");
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
elementList.forEach((elementItem) => {
|
|
1574
|
+
/* 获取对象上的事件 */
|
|
1575
|
+
let events = elementItem[DOMUtilsData.SymbolEvents] || {};
|
|
1576
|
+
eventTypeList.forEach((_eventType_) => {
|
|
1577
|
+
let event: Event = null as any;
|
|
1578
|
+
if (details && details instanceof Event) {
|
|
1579
|
+
event = details;
|
|
1580
|
+
} else {
|
|
1581
|
+
event = new Event(_eventType_);
|
|
1582
|
+
if (details) {
|
|
1583
|
+
Object.keys(details).forEach((keyName) => {
|
|
1584
|
+
(event as any)[keyName] = (details as any)[keyName];
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
if (useDispatchToTriggerEvent == false && _eventType_ in events) {
|
|
1589
|
+
events[_eventType_].forEach((eventsItem: any) => {
|
|
1590
|
+
eventsItem.callback(event);
|
|
1591
|
+
});
|
|
1592
|
+
} else {
|
|
1593
|
+
elementItem.dispatchEvent(event);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
/**
|
|
1600
|
+
* 获取元素相对于文档的偏移坐标(加上文档的滚动条)
|
|
1601
|
+
* @param element 目标元素
|
|
1602
|
+
* @example
|
|
1603
|
+
* // 获取元素a.xx的对于文档的偏移坐标
|
|
1604
|
+
* DOMUtils.offset(document.querySelector("a.xx"))
|
|
1605
|
+
* DOMUtils.offset("a.xx")
|
|
1606
|
+
* > 0
|
|
1607
|
+
*/
|
|
1608
|
+
offset(element: HTMLElement | string) {
|
|
1609
|
+
if (typeof element === "string") {
|
|
1610
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1611
|
+
}
|
|
1612
|
+
if (element == null) {
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1615
|
+
let rect = element.getBoundingClientRect();
|
|
1616
|
+
return {
|
|
1617
|
+
/** y轴偏移 */
|
|
1618
|
+
top: rect.top + globalThis.scrollY,
|
|
1619
|
+
/** x轴偏移 */
|
|
1620
|
+
left: rect.left + globalThis.scrollX,
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* 获取元素的宽度
|
|
1625
|
+
* @param element 要获取宽度的元素
|
|
1626
|
+
* @param isShow 是否已进行isShow,避免爆堆栈
|
|
1627
|
+
* @returns 元素的宽度,单位为像素
|
|
1628
|
+
* @example
|
|
1629
|
+
* // 获取元素a.xx的宽度
|
|
1630
|
+
* DOMUtils.width(document.querySelector("a.xx"))
|
|
1631
|
+
* DOMUtils.width("a.xx")
|
|
1632
|
+
* > 100
|
|
1633
|
+
* // 获取window的宽度
|
|
1634
|
+
* DOMUtils.width(window)
|
|
1635
|
+
* > 400
|
|
1636
|
+
* @example
|
|
1637
|
+
* // 设置元素a.xx的宽度为200
|
|
1638
|
+
* DOMUtils.width(document.querySelector("a.xx"),200)
|
|
1639
|
+
* DOMUtils.width("a.xx",200)
|
|
1640
|
+
*/
|
|
1641
|
+
width(
|
|
1642
|
+
element: HTMLElement | string | Window | Document,
|
|
1643
|
+
isShow?: boolean
|
|
1644
|
+
): number;
|
|
1645
|
+
width(
|
|
1646
|
+
element: HTMLElement | string | Window | Document,
|
|
1647
|
+
isShow: boolean = false
|
|
1648
|
+
) {
|
|
1649
|
+
let DOMUtilsContext = this;
|
|
1650
|
+
if (typeof element === "string") {
|
|
1651
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1652
|
+
}
|
|
1653
|
+
if (element == null) {
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
if (CommonDOMUtils.isWin(element)) {
|
|
1657
|
+
return window.document.documentElement.clientWidth;
|
|
1658
|
+
}
|
|
1659
|
+
if ((element as HTMLElement).nodeType === 9) {
|
|
1660
|
+
/* Document文档节点 */
|
|
1661
|
+
element = element as Document;
|
|
1662
|
+
return Math.max(
|
|
1663
|
+
element.body.scrollWidth,
|
|
1664
|
+
element.documentElement.scrollWidth,
|
|
1665
|
+
element.body.offsetWidth,
|
|
1666
|
+
element.documentElement.offsetWidth,
|
|
1667
|
+
element.documentElement.clientWidth
|
|
1668
|
+
);
|
|
1669
|
+
}
|
|
1670
|
+
if (isShow || (!isShow && CommonDOMUtils.isShow(element as HTMLElement))) {
|
|
1671
|
+
/* 已显示 */
|
|
1672
|
+
/* 不从style中获取对应的宽度,因为可能使用了class定义了width !important */
|
|
1673
|
+
element = element as HTMLElement;
|
|
1674
|
+
/* 如果element.style.width为空 则从css里面获取是否定义了width信息如果定义了 则读取css里面定义的宽度width */
|
|
1675
|
+
if (
|
|
1676
|
+
parseFloat(CommonDOMUtils.getStyleValue(element, "width").toString()) >
|
|
1677
|
+
0
|
|
1678
|
+
) {
|
|
1679
|
+
return parseFloat(
|
|
1680
|
+
CommonDOMUtils.getStyleValue(element, "width").toString()
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
/* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetWidth来进行计算 */
|
|
1685
|
+
if (element.offsetWidth > 0) {
|
|
1686
|
+
let borderLeftWidth = CommonDOMUtils.getStyleValue(
|
|
1687
|
+
element,
|
|
1688
|
+
"borderLeftWidth"
|
|
1689
|
+
);
|
|
1690
|
+
let borderRightWidth = CommonDOMUtils.getStyleValue(
|
|
1691
|
+
element,
|
|
1692
|
+
"borderRightWidth"
|
|
1693
|
+
);
|
|
1694
|
+
let paddingLeft = CommonDOMUtils.getStyleValue(element, "paddingLeft");
|
|
1695
|
+
let paddingRight = CommonDOMUtils.getStyleValue(
|
|
1696
|
+
element,
|
|
1697
|
+
"paddingRight"
|
|
1698
|
+
);
|
|
1699
|
+
let backHeight =
|
|
1700
|
+
parseFloat(element.offsetWidth.toString()) -
|
|
1701
|
+
parseFloat(borderLeftWidth.toString()) -
|
|
1702
|
+
parseFloat(borderRightWidth.toString()) -
|
|
1703
|
+
parseFloat(paddingLeft.toString()) -
|
|
1704
|
+
parseFloat(paddingRight.toString());
|
|
1705
|
+
return parseFloat(backHeight.toString());
|
|
1706
|
+
}
|
|
1707
|
+
return 0;
|
|
1708
|
+
} else {
|
|
1709
|
+
/* 未显示 */
|
|
1710
|
+
element = element as HTMLElement;
|
|
1711
|
+
let { recovery } = CommonDOMUtils.showElement(element);
|
|
1712
|
+
let width = DOMUtilsContext.width(element, true);
|
|
1713
|
+
recovery();
|
|
1714
|
+
return width;
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
/**
|
|
1719
|
+
* 获取元素的高度
|
|
1720
|
+
* @param element 要获取高度的元素
|
|
1721
|
+
* @param isShow 是否已进行isShow,避免爆堆栈
|
|
1722
|
+
* @returns 元素的高度,单位为像素
|
|
1723
|
+
* @example
|
|
1724
|
+
* // 获取元素a.xx的高度
|
|
1725
|
+
* DOMUtils.height(document.querySelector("a.xx"))
|
|
1726
|
+
* DOMUtils.height("a.xx")
|
|
1727
|
+
* > 100
|
|
1728
|
+
* // 获取window的高度
|
|
1729
|
+
* DOMUtils.height(window)
|
|
1730
|
+
* > 700
|
|
1731
|
+
* @example
|
|
1732
|
+
* // 设置元素a.xx的高度为200
|
|
1733
|
+
* DOMUtils.height(document.querySelector("a.xx"),200)
|
|
1734
|
+
* DOMUtils.height("a.xx",200)
|
|
1735
|
+
*/
|
|
1736
|
+
height(
|
|
1737
|
+
element: HTMLElement | string | Window | Document,
|
|
1738
|
+
isShow?: boolean
|
|
1739
|
+
): number;
|
|
1740
|
+
height(
|
|
1741
|
+
element: HTMLElement | string | Window | Document,
|
|
1742
|
+
isShow: boolean = false
|
|
1743
|
+
) {
|
|
1744
|
+
let DOMUtilsContext = this;
|
|
1745
|
+
if (CommonDOMUtils.isWin(element)) {
|
|
1746
|
+
return window.document.documentElement.clientHeight;
|
|
1747
|
+
}
|
|
1748
|
+
if (typeof element === "string") {
|
|
1749
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1750
|
+
}
|
|
1751
|
+
if (element == null) {
|
|
1752
|
+
// @ts-ignore
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
if ((element as Document).nodeType === 9) {
|
|
1756
|
+
element = element as Document;
|
|
1757
|
+
/* Document文档节点 */
|
|
1758
|
+
return Math.max(
|
|
1759
|
+
element.body.scrollHeight,
|
|
1760
|
+
element.documentElement.scrollHeight,
|
|
1761
|
+
element.body.offsetHeight,
|
|
1762
|
+
element.documentElement.offsetHeight,
|
|
1763
|
+
element.documentElement.clientHeight
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
if (isShow || (!isShow && CommonDOMUtils.isShow(element as HTMLElement))) {
|
|
1767
|
+
element = element as HTMLElement;
|
|
1768
|
+
/* 已显示 */
|
|
1769
|
+
/* 从style中获取对应的高度,因为可能使用了class定义了width !important */
|
|
1770
|
+
/* 如果element.style.height为空 则从css里面获取是否定义了height信息如果定义了 则读取css里面定义的高度height */
|
|
1771
|
+
if (
|
|
1772
|
+
parseFloat(CommonDOMUtils.getStyleValue(element, "height").toString()) >
|
|
1773
|
+
0
|
|
1774
|
+
) {
|
|
1775
|
+
return parseFloat(
|
|
1776
|
+
CommonDOMUtils.getStyleValue(element, "height").toString()
|
|
1777
|
+
);
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
/* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetHeight来进行计算 */
|
|
1781
|
+
if (element.offsetHeight > 0) {
|
|
1782
|
+
let borderTopWidth = CommonDOMUtils.getStyleValue(
|
|
1783
|
+
element,
|
|
1784
|
+
"borderTopWidth"
|
|
1785
|
+
);
|
|
1786
|
+
let borderBottomWidth = CommonDOMUtils.getStyleValue(
|
|
1787
|
+
element,
|
|
1788
|
+
"borderBottomWidth"
|
|
1789
|
+
);
|
|
1790
|
+
let paddingTop = CommonDOMUtils.getStyleValue(element, "paddingTop");
|
|
1791
|
+
let paddingBottom = CommonDOMUtils.getStyleValue(
|
|
1792
|
+
element,
|
|
1793
|
+
"paddingBottom"
|
|
1794
|
+
);
|
|
1795
|
+
let backHeight =
|
|
1796
|
+
parseFloat(element.offsetHeight.toString()) -
|
|
1797
|
+
parseFloat(borderTopWidth.toString()) -
|
|
1798
|
+
parseFloat(borderBottomWidth.toString()) -
|
|
1799
|
+
parseFloat(paddingTop.toString()) -
|
|
1800
|
+
parseFloat(paddingBottom.toString());
|
|
1801
|
+
return parseFloat(backHeight.toString());
|
|
1802
|
+
}
|
|
1803
|
+
return 0;
|
|
1804
|
+
} else {
|
|
1805
|
+
/* 未显示 */
|
|
1806
|
+
element = element as HTMLElement;
|
|
1807
|
+
let { recovery } = CommonDOMUtils.showElement(element);
|
|
1808
|
+
let height = DOMUtilsContext.height(element, true);
|
|
1809
|
+
recovery();
|
|
1810
|
+
return height;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
/**
|
|
1814
|
+
* 获取元素的外部宽度(包括边框和外边距)
|
|
1815
|
+
* @param {HTMLElement|string} element 要获取外部宽度的元素
|
|
1816
|
+
* @param {boolean} [isShow=false] 是否已进行isShow,避免爆堆栈
|
|
1817
|
+
* @returns {number} 元素的外部宽度,单位为像素
|
|
1818
|
+
* @example
|
|
1819
|
+
* // 获取元素a.xx的外部宽度
|
|
1820
|
+
* DOMUtils.outerWidth(document.querySelector("a.xx"))
|
|
1821
|
+
* DOMUtils.outerWidth("a.xx")
|
|
1822
|
+
* > 100
|
|
1823
|
+
* // 获取window的外部宽度
|
|
1824
|
+
* DOMUtils.outerWidth(window)
|
|
1825
|
+
* > 400
|
|
1826
|
+
*/
|
|
1827
|
+
outerWidth(
|
|
1828
|
+
element: HTMLElement | string | Window | Document,
|
|
1829
|
+
isShow?: boolean
|
|
1830
|
+
): number;
|
|
1831
|
+
outerWidth(
|
|
1832
|
+
element: HTMLElement | string | Window | Document,
|
|
1833
|
+
isShow: boolean = false
|
|
1834
|
+
) {
|
|
1835
|
+
let DOMUtilsContext = this;
|
|
1836
|
+
if (CommonDOMUtils.isWin(element)) {
|
|
1837
|
+
return window.innerWidth;
|
|
1838
|
+
}
|
|
1839
|
+
if (typeof element === "string") {
|
|
1840
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1841
|
+
}
|
|
1842
|
+
if (element == null) {
|
|
1843
|
+
// @ts-ignore
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
element = element as HTMLElement;
|
|
1847
|
+
if (isShow || (!isShow && CommonDOMUtils.isShow(element))) {
|
|
1848
|
+
let style = getComputedStyle(element, null);
|
|
1849
|
+
let marginLeft = CommonDOMUtils.getStyleValue(style, "marginLeft");
|
|
1850
|
+
let marginRight = CommonDOMUtils.getStyleValue(style, "marginRight");
|
|
1851
|
+
return element.offsetWidth + marginLeft + marginRight;
|
|
1852
|
+
} else {
|
|
1853
|
+
let { recovery } = CommonDOMUtils.showElement(element);
|
|
1854
|
+
let outerWidth = DOMUtilsContext.outerWidth(element, true);
|
|
1855
|
+
recovery();
|
|
1856
|
+
return outerWidth;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
/**
|
|
1860
|
+
* 获取元素的外部高度(包括边框和外边距)
|
|
1861
|
+
* @param {HTMLElement|string} element 要获取外部高度的元素
|
|
1862
|
+
* @param {boolean} [isShow=false] 是否已进行isShow,避免爆堆栈
|
|
1863
|
+
* @returns {number} 元素的外部高度,单位为像素
|
|
1864
|
+
* @example
|
|
1865
|
+
* // 获取元素a.xx的外部高度
|
|
1866
|
+
* DOMUtils.outerHeight(document.querySelector("a.xx"))
|
|
1867
|
+
* DOMUtils.outerHeight("a.xx")
|
|
1868
|
+
* > 100
|
|
1869
|
+
* // 获取window的外部高度
|
|
1870
|
+
* DOMUtils.outerHeight(window)
|
|
1871
|
+
* > 700
|
|
1872
|
+
*/
|
|
1873
|
+
outerHeight(element: HTMLElement | string | Window, isShow?: boolean): number;
|
|
1874
|
+
outerHeight(
|
|
1875
|
+
element: HTMLElement | string | Window,
|
|
1876
|
+
isShow: boolean = false
|
|
1877
|
+
): number {
|
|
1878
|
+
let DOMUtilsContext = this;
|
|
1879
|
+
if (CommonDOMUtils.isWin(element)) {
|
|
1880
|
+
return window.innerHeight;
|
|
1881
|
+
}
|
|
1882
|
+
if (typeof element === "string") {
|
|
1883
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1884
|
+
}
|
|
1885
|
+
if (element == null) {
|
|
1886
|
+
// @ts-ignore
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
element = element as HTMLElement;
|
|
1890
|
+
if (isShow || (!isShow && CommonDOMUtils.isShow(element))) {
|
|
1891
|
+
let style = getComputedStyle(element, null);
|
|
1892
|
+
let marginTop = CommonDOMUtils.getStyleValue(style, "marginTop");
|
|
1893
|
+
let marginBottom = CommonDOMUtils.getStyleValue(style, "marginBottom");
|
|
1894
|
+
return element.offsetHeight + marginTop + marginBottom;
|
|
1895
|
+
} else {
|
|
1896
|
+
let { recovery } = CommonDOMUtils.showElement(element);
|
|
1897
|
+
let outerHeight = DOMUtilsContext.outerHeight(element, true);
|
|
1898
|
+
recovery();
|
|
1899
|
+
return outerHeight;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* 等待文档加载完成后执行指定的函数
|
|
1905
|
+
* @param callback 需要执行的函数
|
|
1906
|
+
* @example
|
|
1907
|
+
* DOMUtils.ready(function(){
|
|
1908
|
+
* console.log("文档加载完毕")
|
|
1909
|
+
* })
|
|
1910
|
+
*/
|
|
1911
|
+
ready(callback: () => void) {
|
|
1912
|
+
let DOMUtilsContext = this;
|
|
1913
|
+
function completed() {
|
|
1914
|
+
DOMUtilsContext.off(document, "DOMContentLoaded", completed);
|
|
1915
|
+
DOMUtilsContext.off(globalThis, "load", completed);
|
|
1916
|
+
callback();
|
|
1917
|
+
}
|
|
1918
|
+
if (
|
|
1919
|
+
document.readyState === "complete" ||
|
|
1920
|
+
(document.readyState !== "loading" &&
|
|
1921
|
+
!(document.documentElement as any).doScroll)
|
|
1922
|
+
) {
|
|
1923
|
+
setTimeout(callback);
|
|
1924
|
+
} else {
|
|
1925
|
+
/* 监听DOMContentLoaded事件 */
|
|
1926
|
+
DOMUtilsContext.on(document, "DOMContentLoaded", completed);
|
|
1927
|
+
/* 监听load事件 */
|
|
1928
|
+
DOMUtilsContext.on(globalThis, "load", completed);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* 在一定时间内改变元素的样式属性,实现动画效果
|
|
1933
|
+
* @param element 需要进行动画的元素
|
|
1934
|
+
* @param styles 动画结束时元素的样式属性
|
|
1935
|
+
* @param duration 动画持续时间,单位为毫秒
|
|
1936
|
+
* @param callback 动画结束后执行的函数
|
|
1937
|
+
* @example
|
|
1938
|
+
* // 监听元素a.xx的从显示变为隐藏
|
|
1939
|
+
* DOMUtils.animate(document.querySelector("a.xx"),{ top:100},1000,function(){
|
|
1940
|
+
* console.log("已往上位移100px")
|
|
1941
|
+
* })
|
|
1942
|
+
*/
|
|
1943
|
+
animate(
|
|
1944
|
+
element: HTMLElement | string,
|
|
1945
|
+
styles: CSSStyleDeclaration,
|
|
1946
|
+
duration: number = 1000,
|
|
1947
|
+
callback: (() => void) | undefined | null = null
|
|
1948
|
+
) {
|
|
1949
|
+
if (typeof element === "string") {
|
|
1950
|
+
element = document.querySelector(element) as HTMLElement;
|
|
1951
|
+
}
|
|
1952
|
+
if (element == null) {
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
if (typeof duration !== "number" || duration <= 0) {
|
|
1956
|
+
throw new TypeError("duration must be a positive number");
|
|
1957
|
+
}
|
|
1958
|
+
if (typeof callback !== "function" && callback !== void 0) {
|
|
1959
|
+
throw new TypeError("callback must be a function or null");
|
|
1960
|
+
}
|
|
1961
|
+
if (typeof styles !== "object" || styles === void 0) {
|
|
1962
|
+
throw new TypeError("styles must be an object");
|
|
1963
|
+
}
|
|
1964
|
+
if (Object.keys(styles).length === 0) {
|
|
1965
|
+
throw new Error("styles must contain at least one property");
|
|
1966
|
+
}
|
|
1967
|
+
let start = performance.now();
|
|
1968
|
+
let from: {
|
|
1969
|
+
[prop: string]: any;
|
|
1970
|
+
} = {};
|
|
1971
|
+
let to: {
|
|
1972
|
+
[prop: string]: any;
|
|
1973
|
+
} = {};
|
|
1974
|
+
for (let prop in styles) {
|
|
1975
|
+
from[prop] = element.style[prop] || getComputedStyle(element)[prop];
|
|
1976
|
+
to[prop] = styles[prop];
|
|
1977
|
+
}
|
|
1978
|
+
let timer = setInterval(function () {
|
|
1979
|
+
let timePassed = performance.now() - start;
|
|
1980
|
+
let progress = timePassed / duration;
|
|
1981
|
+
if (progress > 1) {
|
|
1982
|
+
progress = 1;
|
|
1983
|
+
}
|
|
1984
|
+
for (let prop in styles) {
|
|
1985
|
+
element.style[prop] =
|
|
1986
|
+
from[prop] + (to[prop] - from[prop]) * progress + "px";
|
|
1987
|
+
}
|
|
1988
|
+
if (progress === 1) {
|
|
1989
|
+
clearInterval(timer);
|
|
1990
|
+
if (callback) {
|
|
1991
|
+
callback();
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
}, 10);
|
|
1995
|
+
}
|
|
1996
|
+
/**
|
|
1997
|
+
* 将一个元素包裹在指定的HTML元素中
|
|
1998
|
+
* @param element 要包裹的元素
|
|
1999
|
+
* @param wrapperHTML 要包裹的HTML元素的字符串表示形式
|
|
2000
|
+
* @example
|
|
2001
|
+
* // 将a.xx元素外面包裹一层div
|
|
2002
|
+
* DOMUtils.wrap(document.querySelector("a.xx"),"<div></div>")
|
|
2003
|
+
*/
|
|
2004
|
+
wrap(element: HTMLElement | string | Node, wrapperHTML: string) {
|
|
2005
|
+
if (typeof element === "string") {
|
|
2006
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2007
|
+
}
|
|
2008
|
+
if (element == null) {
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
element = element as HTMLElement;
|
|
2012
|
+
// 创建一个新的div元素,并将wrapperHTML作为其innerHTML
|
|
2013
|
+
let wrapper = document.createElement("div");
|
|
2014
|
+
wrapper.innerHTML = wrapperHTML;
|
|
2015
|
+
|
|
2016
|
+
let wrapperFirstChild = wrapper.firstChild as HTMLElement;
|
|
2017
|
+
// 将要包裹的元素插入目标元素前面
|
|
2018
|
+
(element.parentElement as HTMLElement).insertBefore(
|
|
2019
|
+
wrapperFirstChild,
|
|
2020
|
+
element
|
|
2021
|
+
);
|
|
2022
|
+
|
|
2023
|
+
// 将要包裹的元素移动到wrapper中
|
|
2024
|
+
wrapperFirstChild.appendChild(element);
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* 获取当前元素的前一个兄弟元素
|
|
2028
|
+
* @param element 当前元素
|
|
2029
|
+
* @returns 前一个兄弟元素
|
|
2030
|
+
* @example
|
|
2031
|
+
* // 获取a.xx元素前一个兄弟元素
|
|
2032
|
+
* DOMUtils.prev(document.querySelector("a.xx"))
|
|
2033
|
+
* DOMUtils.prev("a.xx")
|
|
2034
|
+
* > <div ...>....</div>
|
|
2035
|
+
*/
|
|
2036
|
+
prev(element: HTMLElement | string): HTMLElement;
|
|
2037
|
+
prev(element: HTMLElement | string) {
|
|
2038
|
+
if (typeof element === "string") {
|
|
2039
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2040
|
+
}
|
|
2041
|
+
if (element == null) {
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
return element.previousElementSibling as HTMLElement;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
/**
|
|
2048
|
+
* 获取当前元素的后一个兄弟元素
|
|
2049
|
+
* @param element 当前元素
|
|
2050
|
+
* @returns 后一个兄弟元素
|
|
2051
|
+
* @example
|
|
2052
|
+
* // 获取a.xx元素前一个兄弟元素
|
|
2053
|
+
* DOMUtils.next(document.querySelector("a.xx"))
|
|
2054
|
+
* DOMUtils.next("a.xx")
|
|
2055
|
+
* > <div ...>....</div>
|
|
2056
|
+
*/
|
|
2057
|
+
next(element: HTMLElement | string): HTMLElement;
|
|
2058
|
+
next(element: HTMLElement | string) {
|
|
2059
|
+
if (typeof element === "string") {
|
|
2060
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2061
|
+
}
|
|
2062
|
+
if (element == null) {
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
return element.nextElementSibling as HTMLElement;
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* 取消挂载在window下的DOMUtils并返回DOMUtils
|
|
2069
|
+
* @example
|
|
2070
|
+
* let DOMUtils = window.DOMUtils.noConflict()
|
|
2071
|
+
*/
|
|
2072
|
+
noConflict() {
|
|
2073
|
+
if ((window as any).DOMUtils) {
|
|
2074
|
+
CommonDOMUtils.delete(window, "DOMUtils");
|
|
2075
|
+
}
|
|
2076
|
+
(window as any).DOMUtils = this;
|
|
2077
|
+
return this;
|
|
2078
|
+
}
|
|
2079
|
+
/**
|
|
2080
|
+
* 获取当前元素的所有兄弟元素
|
|
2081
|
+
* @param element 当前元素
|
|
2082
|
+
* @returns 所有兄弟元素
|
|
2083
|
+
* @example
|
|
2084
|
+
* // 获取a.xx元素所有兄弟元素
|
|
2085
|
+
* DOMUtils.siblings(document.querySelector("a.xx"))
|
|
2086
|
+
* DOMUtils.siblings("a.xx")
|
|
2087
|
+
* > (3) [div.logo-wrapper, div.forum-block, div.more-btn-desc]
|
|
2088
|
+
*/
|
|
2089
|
+
siblings(element: HTMLElement | string): HTMLElement[];
|
|
2090
|
+
siblings(element: HTMLElement | string) {
|
|
2091
|
+
if (typeof element === "string") {
|
|
2092
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2093
|
+
}
|
|
2094
|
+
if (element == null) {
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
return Array.from(
|
|
2098
|
+
(element.parentElement as HTMLElement)
|
|
2099
|
+
.children as HTMLCollectionOf<HTMLElement>
|
|
2100
|
+
).filter((child) => child !== element);
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* 获取当前元素的父元素
|
|
2104
|
+
* @param element 当前元素
|
|
2105
|
+
* @returns 父元素
|
|
2106
|
+
* @example
|
|
2107
|
+
* // 获取a.xx元素的父元素
|
|
2108
|
+
* DOMUtils.parent(document.querySelector("a.xx"))
|
|
2109
|
+
* DOMUtils.parent("a.xx")
|
|
2110
|
+
* > <div ...>....</div>
|
|
2111
|
+
*/
|
|
2112
|
+
parent(element: HTMLElement | string): HTMLElement;
|
|
2113
|
+
/**
|
|
2114
|
+
* 获取当前元素的父元素
|
|
2115
|
+
* @param element 当前元素
|
|
2116
|
+
* @returns 父元素
|
|
2117
|
+
* @example
|
|
2118
|
+
* // 获取a.xx元素的父元素
|
|
2119
|
+
* DOMUtils.parent(document.querySelector("a.xx"))
|
|
2120
|
+
* DOMUtils.parent("a.xx")
|
|
2121
|
+
* > <div ...>....</div>
|
|
2122
|
+
*/
|
|
2123
|
+
parent(element: HTMLElement[] | NodeList): HTMLElement[];
|
|
2124
|
+
/**
|
|
2125
|
+
* 获取当前元素的父元素
|
|
2126
|
+
* @param element 当前元素
|
|
2127
|
+
* @returns 父元素
|
|
2128
|
+
* @example
|
|
2129
|
+
* // 获取a.xx元素的父元素
|
|
2130
|
+
* DOMUtils.parent(document.querySelector("a.xx"))
|
|
2131
|
+
* DOMUtils.parent("a.xx")
|
|
2132
|
+
* > <div ...>....</div>
|
|
2133
|
+
*/
|
|
2134
|
+
parent(element: HTMLElement | NodeList | string | HTMLElement[]) {
|
|
2135
|
+
let DOMUtilsContext = this;
|
|
2136
|
+
if (typeof element === "string") {
|
|
2137
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2138
|
+
}
|
|
2139
|
+
if (element == null) {
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
if (element instanceof NodeList || element instanceof Array) {
|
|
2143
|
+
element = element as HTMLElement[];
|
|
2144
|
+
let resultArray: HTMLElement[] = [];
|
|
2145
|
+
element.forEach((eleItem) => {
|
|
2146
|
+
resultArray.push(DOMUtilsContext.parent(eleItem));
|
|
2147
|
+
});
|
|
2148
|
+
return resultArray;
|
|
2149
|
+
} else {
|
|
2150
|
+
return element.parentElement;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
/**
|
|
2154
|
+
* 将字符串转为Element元素
|
|
2155
|
+
* @param html
|
|
2156
|
+
* @param useParser (可选)是否使用DOMParser来生成元素,有些时候通过DOMParser生成的元素有点问题
|
|
2157
|
+
* + true 使用DOMPraser来转换字符串
|
|
2158
|
+
* + false 创建一个div,里面放入字符串,然后提取firstChild
|
|
2159
|
+
* @param isComplete (可选)是否是完整的
|
|
2160
|
+
* + true 如果useParser为true,那么返回整个使用DOMParser转换成的Document
|
|
2161
|
+
* 如果useParser为false,返回一个DIV元素,DIV元素内包裹着需要转换的字符串
|
|
2162
|
+
* + false 如果useParser为true,那么返回整个使用DOMParser转换成的Document的body
|
|
2163
|
+
* 如果useParser为false,返回一个DIV元素的firstChild
|
|
2164
|
+
* @example
|
|
2165
|
+
* // 将字符串转为Element元素
|
|
2166
|
+
* DOMUtils.parseHTML("<a href='xxxx'></a>")
|
|
2167
|
+
* > <a href="xxxx"></a>
|
|
2168
|
+
* @example
|
|
2169
|
+
* // 使用DOMParser将字符串转为Element元素
|
|
2170
|
+
* DOMUtils.parseHTML("<a href='xxxx'></a>",true)
|
|
2171
|
+
* > <a href="xxxx"></a>
|
|
2172
|
+
* @example
|
|
2173
|
+
* // 由于需要转换的元素是多个元素,将字符串转为完整的Element元素
|
|
2174
|
+
* DOMUtils.parseHTML("<a href='xxxx'></a><a href='xxxx'></a>",false, true)
|
|
2175
|
+
* > <div><a href="xxxx"></a><a href='xxxx'></a></div>
|
|
2176
|
+
* @example
|
|
2177
|
+
* // 由于需要转换的元素是多个元素,使用DOMParser将字符串转为完整的Element元素
|
|
2178
|
+
* DOMUtils.parseHTML("<a href='xxxx'></a><a href='xxxx'></a>",true, true)
|
|
2179
|
+
* > #document
|
|
2180
|
+
*/
|
|
2181
|
+
parseHTML<T1 extends boolean, T2 extends boolean>(
|
|
2182
|
+
html: string,
|
|
2183
|
+
useParser?: T1,
|
|
2184
|
+
isComplete?: T2
|
|
2185
|
+
): ParseHTMLReturnType<T1, T2>;
|
|
2186
|
+
parseHTML(html: string, useParser = false, isComplete = false) {
|
|
2187
|
+
function parseHTMLByDOMParser() {
|
|
2188
|
+
let parser = new DOMParser();
|
|
2189
|
+
if (isComplete) {
|
|
2190
|
+
return parser.parseFromString(html, "text/html");
|
|
2191
|
+
} else {
|
|
2192
|
+
return parser.parseFromString(html, "text/html").body.firstChild;
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
function parseHTMLByCreateDom() {
|
|
2196
|
+
let tempDIV = document.createElement("div");
|
|
2197
|
+
tempDIV.innerHTML = html;
|
|
2198
|
+
if (isComplete) {
|
|
2199
|
+
return tempDIV;
|
|
2200
|
+
} else {
|
|
2201
|
+
return tempDIV.firstChild;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
if (useParser) {
|
|
2205
|
+
return parseHTMLByDOMParser();
|
|
2206
|
+
} else {
|
|
2207
|
+
return parseHTMLByCreateDom();
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
/**
|
|
2211
|
+
* 当鼠标移入或移出元素时触发事件
|
|
2212
|
+
* @param element 当前元素
|
|
2213
|
+
* @param handler 事件处理函数
|
|
2214
|
+
* @param option 配置
|
|
2215
|
+
* @example
|
|
2216
|
+
* // 监听a.xx元素的移入或移出
|
|
2217
|
+
* DOMUtils.hover(document.querySelector("a.xx"),()=>{
|
|
2218
|
+
* console.log("移入/移除");
|
|
2219
|
+
* })
|
|
2220
|
+
* DOMUtils.hover("a.xx",()=>{
|
|
2221
|
+
* console.log("移入/移除");
|
|
2222
|
+
* })
|
|
2223
|
+
*/
|
|
2224
|
+
hover(
|
|
2225
|
+
element: HTMLElement | string,
|
|
2226
|
+
handler: (event: Event) => void,
|
|
2227
|
+
option?: boolean | AddEventListenerOptions
|
|
2228
|
+
) {
|
|
2229
|
+
let DOMUtilsContext = this;
|
|
2230
|
+
if (typeof element === "string") {
|
|
2231
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2232
|
+
}
|
|
2233
|
+
if (element == null) {
|
|
2234
|
+
return;
|
|
2235
|
+
}
|
|
2236
|
+
DOMUtilsContext.on(element, "mouseenter", null, handler, option);
|
|
2237
|
+
DOMUtilsContext.on(element, "mouseleave", null, handler, option);
|
|
2238
|
+
}
|
|
2239
|
+
/**
|
|
2240
|
+
* 显示元素
|
|
2241
|
+
* @param target 当前元素
|
|
2242
|
+
* @example
|
|
2243
|
+
* // 显示a.xx元素
|
|
2244
|
+
* DOMUtils.show(document.querySelector("a.xx"))
|
|
2245
|
+
* DOMUtils.show(document.querySelectorAll("a.xx"))
|
|
2246
|
+
* DOMUtils.show("a.xx")
|
|
2247
|
+
*/
|
|
2248
|
+
show(target: HTMLElement | string | NodeList | HTMLElement[]) {
|
|
2249
|
+
let DOMUtilsContext = this;
|
|
2250
|
+
if (target == null) {
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2253
|
+
if (typeof target === "string") {
|
|
2254
|
+
target = document.querySelectorAll(target);
|
|
2255
|
+
}
|
|
2256
|
+
if (target instanceof NodeList || target instanceof Array) {
|
|
2257
|
+
target = target as HTMLElement[];
|
|
2258
|
+
for (const element of target) {
|
|
2259
|
+
DOMUtilsContext.show(element);
|
|
2260
|
+
}
|
|
2261
|
+
} else {
|
|
2262
|
+
target.style.display = "";
|
|
2263
|
+
if (!CommonDOMUtils.isShow(target)) {
|
|
2264
|
+
/* 仍然是不显示,尝试使用强覆盖 */
|
|
2265
|
+
target.style.setProperty("display", "unset", "important");
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* 隐藏元素
|
|
2271
|
+
* @param target 当前元素
|
|
2272
|
+
* @example
|
|
2273
|
+
* // 隐藏a.xx元素
|
|
2274
|
+
* DOMUtils.hide(document.querySelector("a.xx"))
|
|
2275
|
+
* DOMUtils.hide(document.querySelectorAll("a.xx"))
|
|
2276
|
+
* DOMUtils.hide("a.xx")
|
|
2277
|
+
*/
|
|
2278
|
+
hide(target: HTMLElement | string | NodeList | HTMLElement[]) {
|
|
2279
|
+
let DOMUtilsContext = this;
|
|
2280
|
+
if (target == null) {
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
if (typeof target === "string") {
|
|
2284
|
+
target = document.querySelectorAll(target);
|
|
2285
|
+
}
|
|
2286
|
+
if (target instanceof NodeList || target instanceof Array) {
|
|
2287
|
+
target = target as HTMLElement[];
|
|
2288
|
+
for (const element of target) {
|
|
2289
|
+
DOMUtilsContext.hide(element);
|
|
2290
|
+
}
|
|
2291
|
+
} else {
|
|
2292
|
+
target.style.display = "none";
|
|
2293
|
+
if (CommonDOMUtils.isShow(target)) {
|
|
2294
|
+
/* 仍然是显示,尝试使用强覆盖 */
|
|
2295
|
+
target.style.setProperty("display", "none", "important");
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
/**
|
|
2300
|
+
* 当按键松开时触发事件
|
|
2301
|
+
* keydown - > keypress - > keyup
|
|
2302
|
+
* @param target 当前元素
|
|
2303
|
+
* @param handler 事件处理函数
|
|
2304
|
+
* @param option 配置
|
|
2305
|
+
* @example
|
|
2306
|
+
* // 监听a.xx元素的按键松开
|
|
2307
|
+
* DOMUtils.keyup(document.querySelector("a.xx"),()=>{
|
|
2308
|
+
* console.log("按键松开");
|
|
2309
|
+
* })
|
|
2310
|
+
* DOMUtils.keyup("a.xx",()=>{
|
|
2311
|
+
* console.log("按键松开");
|
|
2312
|
+
* })
|
|
2313
|
+
*/
|
|
2314
|
+
keyup(
|
|
2315
|
+
target: HTMLElement | string | Window | typeof globalThis,
|
|
2316
|
+
handler: (event: KeyboardEvent) => void,
|
|
2317
|
+
option?: boolean | AddEventListenerOptions
|
|
2318
|
+
) {
|
|
2319
|
+
let DOMUtilsContext = this;
|
|
2320
|
+
if (target == null) {
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
if (typeof target === "string") {
|
|
2324
|
+
target = document.querySelector(target) as HTMLElement;
|
|
2325
|
+
}
|
|
2326
|
+
DOMUtilsContext.on(target, "keyup", null, handler, option);
|
|
2327
|
+
}
|
|
2328
|
+
/**
|
|
2329
|
+
* 当按键按下时触发事件
|
|
2330
|
+
* keydown - > keypress - > keyup
|
|
2331
|
+
* @param target 目标
|
|
2332
|
+
* @param handler 事件处理函数
|
|
2333
|
+
* @param option 配置
|
|
2334
|
+
* @example
|
|
2335
|
+
* // 监听a.xx元素的按键按下
|
|
2336
|
+
* DOMUtils.keydown(document.querySelector("a.xx"),()=>{
|
|
2337
|
+
* console.log("按键按下");
|
|
2338
|
+
* })
|
|
2339
|
+
* DOMUtils.keydown("a.xx",()=>{
|
|
2340
|
+
* console.log("按键按下");
|
|
2341
|
+
* })
|
|
2342
|
+
*/
|
|
2343
|
+
keydown(
|
|
2344
|
+
target: HTMLElement | Window | typeof globalThis | string,
|
|
2345
|
+
handler: (event: KeyboardEvent) => void,
|
|
2346
|
+
option?: boolean | AddEventListenerOptions
|
|
2347
|
+
) {
|
|
2348
|
+
let DOMUtilsContext = this;
|
|
2349
|
+
if (target == null) {
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
if (typeof target === "string") {
|
|
2353
|
+
target = document.querySelector(target) as HTMLElement;
|
|
2354
|
+
}
|
|
2355
|
+
DOMUtilsContext.on(target, "keydown", null, handler, option);
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* 当按键按下时触发事件
|
|
2359
|
+
* keydown - > keypress - > keyup
|
|
2360
|
+
* @param target 目标
|
|
2361
|
+
* @param handler 事件处理函数
|
|
2362
|
+
* @param option 配置
|
|
2363
|
+
* @example
|
|
2364
|
+
* // 监听a.xx元素的按键按下
|
|
2365
|
+
* DOMUtils.keypress(document.querySelector("a.xx"),()=>{
|
|
2366
|
+
* console.log("按键按下");
|
|
2367
|
+
* })
|
|
2368
|
+
* DOMUtils.keypress("a.xx",()=>{
|
|
2369
|
+
* console.log("按键按下");
|
|
2370
|
+
* })
|
|
2371
|
+
*/
|
|
2372
|
+
keypress(
|
|
2373
|
+
target: HTMLElement | Window | typeof globalThis | string,
|
|
2374
|
+
handler: (event: KeyboardEvent) => void,
|
|
2375
|
+
option?: boolean | AddEventListenerOptions
|
|
2376
|
+
) {
|
|
2377
|
+
let DOMUtilsContext = this;
|
|
2378
|
+
if (target == null) {
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2381
|
+
if (typeof target === "string") {
|
|
2382
|
+
target = document.querySelector(target) as HTMLElement;
|
|
2383
|
+
}
|
|
2384
|
+
DOMUtilsContext.on(target, "keypress", null, handler, option);
|
|
2385
|
+
}
|
|
2386
|
+
/**
|
|
2387
|
+
* 淡入元素
|
|
2388
|
+
* @param element 当前元素
|
|
2389
|
+
* @param duration 动画持续时间(毫秒),默认400毫秒
|
|
2390
|
+
* @param callback 动画结束的回调
|
|
2391
|
+
* @example
|
|
2392
|
+
* // 元素a.xx淡入
|
|
2393
|
+
* DOMUtils.fadeIn(document.querySelector("a.xx"),2500,()=>{
|
|
2394
|
+
* console.log("淡入完毕");
|
|
2395
|
+
* })
|
|
2396
|
+
* DOMUtils.fadeIn("a.xx",undefined,()=>{
|
|
2397
|
+
* console.log("淡入完毕");
|
|
2398
|
+
* })
|
|
2399
|
+
*/
|
|
2400
|
+
fadeIn(
|
|
2401
|
+
element: HTMLElement | string,
|
|
2402
|
+
duration: number = 400,
|
|
2403
|
+
callback?: () => void
|
|
2404
|
+
) {
|
|
2405
|
+
if (element == null) {
|
|
2406
|
+
return;
|
|
2407
|
+
}
|
|
2408
|
+
if (typeof element === "string") {
|
|
2409
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2410
|
+
}
|
|
2411
|
+
element = element as HTMLElement;
|
|
2412
|
+
element.style.opacity = "0";
|
|
2413
|
+
element.style.display = "";
|
|
2414
|
+
let start: number = null as any;
|
|
2415
|
+
let timer: number = null as any;
|
|
2416
|
+
function step(timestamp: number) {
|
|
2417
|
+
if (!start) start = timestamp;
|
|
2418
|
+
let progress = timestamp - start;
|
|
2419
|
+
element = element as HTMLElement;
|
|
2420
|
+
element.style.opacity = Math.min(progress / duration, 1).toString();
|
|
2421
|
+
if (progress < duration) {
|
|
2422
|
+
window.requestAnimationFrame(step);
|
|
2423
|
+
} else {
|
|
2424
|
+
if (callback && typeof callback === "function") {
|
|
2425
|
+
callback();
|
|
2426
|
+
}
|
|
2427
|
+
window.cancelAnimationFrame(timer);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
timer = window.requestAnimationFrame(step);
|
|
2431
|
+
}
|
|
2432
|
+
/**
|
|
2433
|
+
* 淡出元素
|
|
2434
|
+
* @param element 当前元素
|
|
2435
|
+
* @param duration 动画持续时间(毫秒),默认400毫秒
|
|
2436
|
+
* @param callback 动画结束的回调
|
|
2437
|
+
* @example
|
|
2438
|
+
* // 元素a.xx淡出
|
|
2439
|
+
* DOMUtils.fadeOut(document.querySelector("a.xx"),2500,()=>{
|
|
2440
|
+
* console.log("淡出完毕");
|
|
2441
|
+
* })
|
|
2442
|
+
* DOMUtils.fadeOut("a.xx",undefined,()=>{
|
|
2443
|
+
* console.log("淡出完毕");
|
|
2444
|
+
* })
|
|
2445
|
+
*/
|
|
2446
|
+
fadeOut(
|
|
2447
|
+
element: HTMLElement | string,
|
|
2448
|
+
duration: number = 400,
|
|
2449
|
+
callback?: () => void
|
|
2450
|
+
) {
|
|
2451
|
+
if (element == null) {
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
if (typeof element === "string") {
|
|
2455
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2456
|
+
}
|
|
2457
|
+
element = element as HTMLElement;
|
|
2458
|
+
element.style.opacity = "1";
|
|
2459
|
+
let start: number = null as any;
|
|
2460
|
+
let timer: number = null as any;
|
|
2461
|
+
function step(timestamp: number) {
|
|
2462
|
+
if (!start) start = timestamp;
|
|
2463
|
+
let progress = timestamp - start;
|
|
2464
|
+
element = element as HTMLElement;
|
|
2465
|
+
element.style.opacity = Math.max(1 - progress / duration, 0).toString();
|
|
2466
|
+
if (progress < duration) {
|
|
2467
|
+
window.requestAnimationFrame(step);
|
|
2468
|
+
} else {
|
|
2469
|
+
element.style.display = "none";
|
|
2470
|
+
if (typeof callback === "function") {
|
|
2471
|
+
callback();
|
|
2472
|
+
}
|
|
2473
|
+
window.cancelAnimationFrame(timer);
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
timer = window.requestAnimationFrame(step);
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* 切换元素的显示和隐藏状态
|
|
2480
|
+
* @param element 当前元素
|
|
2481
|
+
* @example
|
|
2482
|
+
* // 如果元素a.xx当前是隐藏,则显示,如果是显示,则隐藏
|
|
2483
|
+
* DOMUtils.toggle(document.querySelector("a.xx"))
|
|
2484
|
+
* DOMUtils.toggle("a.xx")
|
|
2485
|
+
*/
|
|
2486
|
+
toggle(element: HTMLElement | string) {
|
|
2487
|
+
let DOMUtilsContext = this;
|
|
2488
|
+
if (typeof element === "string") {
|
|
2489
|
+
element = document.querySelector(element) as HTMLElement;
|
|
2490
|
+
}
|
|
2491
|
+
if (element == null) {
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
if (getComputedStyle(element).getPropertyValue("display") === "none") {
|
|
2495
|
+
DOMUtilsContext.show(element);
|
|
2496
|
+
} else {
|
|
2497
|
+
DOMUtilsContext.hide(element);
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
let domUtils = new DOMUtils();
|
|
2503
|
+
|
|
2504
|
+
export { domUtils as DOMUtils };
|