@whitesev/domutils 1.6.5 → 1.6.7

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/src/DOMUtils.ts CHANGED
@@ -1,2005 +1,1998 @@
1
1
  import { DOMUtilsCommonUtils } from "./DOMUtilsCommonUtils";
2
2
  import { DOMUtilsEvent } from "./DOMUtilsEvent";
3
3
  import type { DOMUtilsCreateElementAttributesMap } from "./types/DOMUtilsEvent";
4
- import { ParseHTMLReturnType, type DOMUtilsTargetElementType } from "./types/global";
4
+ import { type ParseHTMLReturnType, type DOMUtilsTargetElementType } from "./types/global";
5
5
  import type { WindowApiOption } from "./types/WindowApi";
6
+ import { version } from "./../package.json";
6
7
 
7
8
  class DOMUtils extends DOMUtilsEvent {
8
- constructor(option?: WindowApiOption) {
9
- super(option);
10
- }
11
- /** 版本号 */
12
- version = "2025.8.11";
13
- /**
14
- * 获取元素的属性值
15
- * @param element 目标元素
16
- * @param attrName 属性名
17
- * @example
18
- * // 获取a.xx元素的href属性
19
- * DOMUtils.attr(document.querySelector("a.xx"),"href");
20
- * DOMUtils.attr("a.xx","href");
21
- * > https://xxxx....
22
- */
23
- attr(element: DOMUtilsTargetElementType | Element, attrName: string): string;
24
- /**
25
- * 设置元素的属性值
26
- * @param element 目标元素
27
- * @param attrName 属性名
28
- * @param attrValue 属性值
29
- * @example
30
- * // 修改a.xx元素的href属性为abcd
31
- * DOMUtils.attr(document.querySelector("a.xx"),"href","abcd");
32
- * DOMUtils.attr("a.xx","href","abcd");
33
- */
34
- attr(
35
- element: DOMUtilsTargetElementType | Element,
36
- attrName: string,
37
- attrValue: string | boolean | number
38
- ): void;
39
- attr(element: DOMUtilsTargetElementType | Element, attrName: string, attrValue?: any) {
40
- let DOMUtilsContext = this;
41
- if (typeof element === "string") {
42
- element = DOMUtilsContext.selectorAll(element);
43
- }
44
- if (element == null) {
45
- return;
46
- }
47
- if (DOMUtilsCommonUtils.isNodeList(element)) {
48
- if (attrValue == null) {
49
- // 获取属性
50
- return DOMUtilsContext.attr(element[0] as HTMLElement, attrName, attrValue);
51
- } else {
52
- // 设置属性
53
- element.forEach(($ele) => {
54
- DOMUtilsContext.attr($ele as HTMLElement, attrName, attrValue);
55
- });
56
- return;
57
- }
58
- }
59
- if (attrValue == null) {
60
- return element.getAttribute(attrName);
61
- } else {
62
- element.setAttribute(attrName, attrValue);
63
- }
64
- }
65
- /**
66
- * 创建元素
67
- * @param tagName 标签名
68
- * @param property 属性
69
- * @param attributes 元素上的自定义属性
70
- * @example
71
- * // 创建一个DIV元素,且属性class为xxx
72
- * DOMUtils.createElement("div",undefined,{ class:"xxx" });
73
- * > <div class="xxx"></div>
74
- * @example
75
- * // 创建一个DIV元素
76
- * DOMUtils.createElement("div");
77
- * > <div></div>
78
- * @example
79
- * // 创建一个DIV元素
80
- * DOMUtils.createElement("div","测试");
81
- * > <div>测试</div>
82
- */
83
- createElement<K extends keyof HTMLElementTagNameMap>(
84
- /** 元素名 */
85
- tagName: K,
86
- /** 属性 */
87
- property?:
88
- | ({
89
- [P in keyof HTMLElementTagNameMap[K]]?: HTMLElementTagNameMap[K][P];
90
- } & {
91
- [key: string]: any;
92
- })
93
- | string,
94
- /** 自定义属性 */
95
- attributes?: DOMUtilsCreateElementAttributesMap
96
- ): HTMLElementTagNameMap[K] {
97
- let DOMUtilsContext = this;
98
- let tempElement = DOMUtilsContext.windowApi.document.createElement(tagName);
99
- if (typeof property === "string") {
100
- DOMUtilsContext.html(tempElement, property);
101
- return tempElement;
102
- }
103
- if (property == null) {
104
- property = {};
105
- }
106
- if (attributes == null) {
107
- attributes = {};
108
- }
109
- Object.keys(property).forEach((key) => {
110
- let value = property[key];
111
- if (key === "innerHTML") {
112
- DOMUtilsContext.html(tempElement, value);
113
- return;
114
- }
115
- (tempElement as any)[key] = value;
116
- });
117
- Object.keys(attributes).forEach((key) => {
118
- let value = attributes[key];
119
- if (typeof value === "object") {
120
- /* object转字符串 */
121
- value = JSON.stringify(value);
122
- } else if (typeof value === "function") {
123
- /* function转字符串 */
124
- value = value.toString();
125
- }
126
- tempElement.setAttribute(key, value);
127
- });
128
- return tempElement;
129
- }
9
+ constructor(option?: WindowApiOption) {
10
+ super(option);
11
+ }
12
+ /** 版本号 */
13
+ version = version;
14
+ /**
15
+ * 获取元素的属性值
16
+ * @param element 目标元素
17
+ * @param attrName 属性名
18
+ * @example
19
+ * // 获取a.xx元素的href属性
20
+ * DOMUtils.attr(document.querySelector("a.xx"),"href");
21
+ * DOMUtils.attr("a.xx","href");
22
+ * > https://xxxx....
23
+ */
24
+ attr(element: DOMUtilsTargetElementType | Element, attrName: string): string;
25
+ /**
26
+ * 设置元素的属性值
27
+ * @param element 目标元素
28
+ * @param attrName 属性名
29
+ * @param attrValue 属性值
30
+ * @example
31
+ * // 修改a.xx元素的href属性为abcd
32
+ * DOMUtils.attr(document.querySelector("a.xx"),"href","abcd");
33
+ * DOMUtils.attr("a.xx","href","abcd");
34
+ */
35
+ attr(element: DOMUtilsTargetElementType | Element, attrName: string, attrValue: string | boolean | number): void;
36
+ attr(element: DOMUtilsTargetElementType | Element, attrName: string, attrValue?: any) {
37
+ const DOMUtilsContext = this;
38
+ if (typeof element === "string") {
39
+ element = DOMUtilsContext.selectorAll(element);
40
+ }
41
+ if (element == null) {
42
+ return;
43
+ }
44
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
45
+ if (attrValue == null) {
46
+ // 获取属性
47
+ return DOMUtilsContext.attr(element[0] as HTMLElement, attrName, attrValue);
48
+ } else {
49
+ // 设置属性
50
+ element.forEach(($ele) => {
51
+ DOMUtilsContext.attr($ele as HTMLElement, attrName, attrValue);
52
+ });
53
+ return;
54
+ }
55
+ }
56
+ if (attrValue == null) {
57
+ return element.getAttribute(attrName);
58
+ } else {
59
+ element.setAttribute(attrName, attrValue);
60
+ }
61
+ }
62
+ /**
63
+ * 创建元素
64
+ * @param tagName 标签名
65
+ * @param property 属性
66
+ * @param attributes 元素上的自定义属性
67
+ * @example
68
+ * // 创建一个DIV元素,且属性class为xxx
69
+ * DOMUtils.createElement("div",undefined,{ class:"xxx" });
70
+ * > <div class="xxx"></div>
71
+ * @example
72
+ * // 创建一个DIV元素
73
+ * DOMUtils.createElement("div");
74
+ * > <div></div>
75
+ * @example
76
+ * // 创建一个DIV元素
77
+ * DOMUtils.createElement("div","测试");
78
+ * > <div>测试</div>
79
+ */
80
+ createElement<K extends keyof HTMLElementTagNameMap>(
81
+ /** 元素名 */
82
+ tagName: K,
83
+ /** 属性 */
84
+ property?:
85
+ | ({
86
+ [P in keyof HTMLElementTagNameMap[K]]?: HTMLElementTagNameMap[K][P];
87
+ } & {
88
+ [key: string]: any;
89
+ })
90
+ | string,
91
+ /** 自定义属性 */
92
+ attributes?: DOMUtilsCreateElementAttributesMap
93
+ ): HTMLElementTagNameMap[K];
94
+ /**
95
+ * 创建元素
96
+ * @param tagName 自定义的标签名
97
+ * @param property 属性
98
+ * @param attributes 元素上的自定义属性
99
+ * @example
100
+ * // 创建一个custom-div元素,且属性class为xxx
101
+ * DOMUtils.createElement("custom-div",undefined,{ class:"xxx" });
102
+ * > <custom-div class="xxx"></custom-div>
103
+ * @example
104
+ * // 创建一个custom-div元素
105
+ * DOMUtils.createElement("custom-div");
106
+ * > <custom-div></custom-div>
107
+ * @example
108
+ * // 创建一个custom-div元素
109
+ * DOMUtils.createElement("custom-div","测试");
110
+ * > <custom-div>测试</custom-div>
111
+ */
112
+ createElement(
113
+ /** 元素名 */
114
+ tagName: string,
115
+ /** 属性 */
116
+ property?:
117
+ | ({
118
+ [P in keyof HTMLElement]?: HTMLElement[P];
119
+ } & {
120
+ [key: string]: any;
121
+ })
122
+ | string,
123
+ /** 自定义属性 */
124
+ attributes?: DOMUtilsCreateElementAttributesMap
125
+ ): HTMLElement;
126
+ createElement<K extends keyof HTMLElementTagNameMap>(
127
+ /** 元素名 */
128
+ tagName: K,
129
+ /** 属性 */
130
+ property?:
131
+ | ({
132
+ [P in keyof HTMLElementTagNameMap[K]]?: HTMLElementTagNameMap[K][P];
133
+ } & {
134
+ [key: string]: any;
135
+ })
136
+ | string,
137
+ /** 自定义属性 */
138
+ attributes?: DOMUtilsCreateElementAttributesMap
139
+ ): HTMLElementTagNameMap[K] {
140
+ const DOMUtilsContext = this;
141
+ const tempElement = DOMUtilsContext.windowApi.document.createElement(tagName);
142
+ if (typeof property === "string") {
143
+ DOMUtilsContext.html(tempElement, property);
144
+ return tempElement;
145
+ }
146
+ if (property == null) {
147
+ property = {};
148
+ }
149
+ if (attributes == null) {
150
+ attributes = {};
151
+ }
152
+ Object.keys(property).forEach((key) => {
153
+ const value = property[key];
154
+ if (key === "innerHTML") {
155
+ DOMUtilsContext.html(tempElement, value);
156
+ return;
157
+ }
158
+ (tempElement as any)[key] = value;
159
+ });
160
+ Object.keys(attributes).forEach((key) => {
161
+ let value = attributes[key];
162
+ if (typeof value === "object") {
163
+ /* object转字符串 */
164
+ value = JSON.stringify(value);
165
+ } else if (typeof value === "function") {
166
+ /* function转字符串 */
167
+ value = value.toString();
168
+ }
169
+ tempElement.setAttribute(key, value);
170
+ });
171
+ return tempElement;
172
+ }
173
+ /**
174
+ * 获取元素的样式属性值
175
+ * @param element 目标元素
176
+ * @param property 样式属性名或包含多个属性名和属性值的对象
177
+ * @example
178
+ * // 获取元素a.xx的CSS属性display
179
+ * DOMUtils.css(document.querySelector("a.xx"),"display");
180
+ * DOMUtils.css("a.xx","display");
181
+ * > "none"
182
+ * */
183
+ css(element: DOMUtilsTargetElementType, property: keyof Omit<CSSStyleDeclaration, "zIndex"> | "z-index"): string;
184
+ /**
185
+ * 获取元素的样式属性值
186
+ * @param element 目标元素
187
+ * @param property 样式属性名或包含多个属性名和属性值的对象
188
+ * @example
189
+ * // 获取元素a.xx的CSS属性display
190
+ * DOMUtils.css(document.querySelector("a.xx"),"display");
191
+ * DOMUtils.css("a.xx","display");
192
+ * > "none"
193
+ * */
194
+ css(element: DOMUtilsTargetElementType, property: string): string;
195
+ /**
196
+ * 设置元素的样式属性
197
+ * @param element 目标元素
198
+ * @param property 样式属性名或包含多个属性名和属性值的对象
199
+ * @param value 样式属性值
200
+ * @example
201
+ * // 设置元素a.xx的CSS属性display为block
202
+ * DOMUtils.css(document.querySelector("a.xx"),"display","block");
203
+ * DOMUtils.css(document.querySelector("a.xx"),"display","block !important");
204
+ * DOMUtils.css("a.xx","display","block");
205
+ * DOMUtils.css("a.xx","display","block !important");
206
+ * @example
207
+ * // 设置元素a.xx的CSS属性top为10px
208
+ * DOMUtils.css(document.querySelector("a.xx"),"top","10px");
209
+ * DOMUtils.css(document.querySelector("a.xx"),"top",10);
210
+ * */
211
+ css(
212
+ element: DOMUtilsTargetElementType,
213
+ property: (keyof Omit<CSSStyleDeclaration, "zIndex"> | "z-index") & string,
214
+ value: string | number
215
+ ): string;
216
+ /**
217
+ * 设置元素的样式属性
218
+ * @param element 目标元素
219
+ * @param property 样式属性名或包含多个属性名和属性值的对象
220
+ * @param value 样式属性值
221
+ * @example
222
+ * // 设置元素a.xx的CSS属性display为block
223
+ * DOMUtils.css(document.querySelector("a.xx"),{ display: "block" }});
224
+ * DOMUtils.css(document.querySelector("a.xx"),{ display: "block !important" }});
225
+ * @example
226
+ * // 设置元素a.xx的CSS属性top为10px
227
+ * DOMUtils.css(document.querySelector("a.xx"),{ top: "10px" });
228
+ * DOMUtils.css(document.querySelector("a.xx"),{ top: 10 });
229
+ * */
230
+ css(
231
+ element: DOMUtilsTargetElementType,
232
+ property:
233
+ | {
234
+ [P in keyof Omit<CSSStyleDeclaration, "zIndex">]?: CSSStyleDeclaration[P];
235
+ }
236
+ | {
237
+ "z-index": string | number;
238
+ }
239
+ | {
240
+ [key: string]: string | number;
241
+ }
242
+ ): string;
243
+ css(
244
+ element: DOMUtilsTargetElementType,
245
+ property:
246
+ | keyof Omit<CSSStyleDeclaration, "zIndex">
247
+ | string
248
+ | {
249
+ [P in keyof Omit<CSSStyleDeclaration, "zIndex">]?: string | number | CSSStyleDeclaration[P];
250
+ },
251
+ value?: string | number
252
+ ) {
253
+ const DOMUtilsContext = this;
254
+ /**
255
+ * 把纯数字没有px的加上
256
+ */
257
+ function handlePixe(propertyName: string, propertyValue: string | number) {
258
+ const allowAddPixe = ["width", "height", "top", "left", "right", "bottom", "font-size"];
259
+ if (typeof propertyValue === "number") {
260
+ propertyValue = propertyValue.toString();
261
+ }
262
+ if (typeof propertyValue === "string" && allowAddPixe.includes(propertyName) && propertyValue.match(/[0-9]$/gi)) {
263
+ propertyValue = propertyValue + "px";
264
+ }
265
+ return propertyValue;
266
+ }
267
+ if (typeof element === "string") {
268
+ element = DOMUtilsContext.selectorAll(element);
269
+ }
270
+ if (element == null) {
271
+ return;
272
+ }
273
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
274
+ if (typeof property === "string") {
275
+ if (value == null) {
276
+ // 获取属性
277
+ return DOMUtilsContext.css(element[0] as HTMLElement, property);
278
+ } else {
279
+ // 设置属性
280
+ element.forEach(($ele) => {
281
+ DOMUtilsContext.css($ele as HTMLElement, property);
282
+ });
283
+ return;
284
+ }
285
+ } else if (typeof property === "object") {
286
+ // 设置属性
287
+ element.forEach(($ele) => {
288
+ DOMUtilsContext.css($ele as HTMLElement, property as object);
289
+ });
290
+ return;
291
+ }
292
+ return;
293
+ }
294
+ const setStyleProperty = (propertyName: string, propertyValue: string | number) => {
295
+ if (typeof propertyValue === "string" && propertyValue.trim().endsWith("!important")) {
296
+ propertyValue = propertyValue
297
+ .trim()
298
+ .replace(/!important$/gi, "")
299
+ .trim();
300
+ element.style.setProperty(propertyName, propertyValue, "important");
301
+ } else {
302
+ propertyValue = handlePixe(propertyName, propertyValue);
303
+ element.style.setProperty(propertyName, propertyValue);
304
+ }
305
+ };
306
+ if (typeof property === "string") {
307
+ if (value == null) {
308
+ return DOMUtilsContext.windowApi.globalThis.getComputedStyle(element).getPropertyValue(property);
309
+ } else {
310
+ setStyleProperty(property, value);
311
+ }
312
+ } else if (typeof property === "object") {
313
+ for (const prop in property) {
314
+ const value = property[prop];
315
+ setStyleProperty(prop, value!);
316
+ }
317
+ } else {
318
+ // 其他情况
319
+ throw new TypeError("property must be string or object");
320
+ }
321
+ }
322
+ /**
323
+ * 获取元素的文本内容,优先返回textContent
324
+ * @param element 目标元素
325
+ * @returns 如果传入了text,则返回undefined;否则返回文本内容
326
+ * @example
327
+ * // 设置元素a.xx的文本内容为abcd
328
+ * DOMUtils.text(document.querySelector("a.xx"),"abcd")
329
+ * DOMUtils.text("a.xx","abcd")
330
+ * DOMUtils.text("a.xx",document.querySelector("b"))
331
+ * */
332
+ text(element: DOMUtilsTargetElementType | Element | DocumentFragment | Node): string;
333
+ /**
334
+ * 设置元素的文本内容
335
+ * @param element 目标元素
336
+ * @param text (可选)文本内容
337
+ * @returns 如果传入了text,则返回undefined;否则返回文本内容
338
+ * @example
339
+ * // 设置元素a.xx的文本内容为abcd
340
+ * DOMUtils.text(document.querySelector("a.xx"),"abcd")
341
+ * DOMUtils.text("a.xx","abcd")
342
+ * DOMUtils.text("a.xx",document.querySelector("b"))
343
+ * */
344
+ text(
345
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Node,
346
+ text: string | HTMLElement | Element | number
347
+ ): void;
348
+ text(element: DOMUtilsTargetElementType | Element | DocumentFragment | Node, text?: any) {
349
+ const DOMUtilsContext = this;
350
+ if (typeof element === "string") {
351
+ element = DOMUtilsContext.selectorAll(element);
352
+ }
353
+ if (element == null) {
354
+ return;
355
+ }
356
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
357
+ if (text == null) {
358
+ // 获取
359
+ return DOMUtilsContext.text(element[0] as HTMLElement);
360
+ } else {
361
+ // 设置
362
+ element.forEach(($ele) => {
363
+ DOMUtilsContext.text($ele as HTMLElement, text);
364
+ });
365
+ }
366
+ return;
367
+ }
368
+ if (text == null) {
369
+ return element.textContent || (<HTMLElement>element).innerText;
370
+ } else {
371
+ if (text instanceof Node) {
372
+ text = text.textContent || (text as HTMLElement).innerText;
373
+ }
374
+ if ("textContent" in element) {
375
+ element.textContent = text as string;
376
+ } else if ("innerText" in element) {
377
+ (element as HTMLElement).innerText = text as string;
378
+ }
379
+ }
380
+ }
130
381
 
131
- /**
132
- * 获取元素的样式属性值
133
- * @param element 目标元素
134
- * @param property 样式属性名或包含多个属性名和属性值的对象
135
- * @example
136
- * // 获取元素a.xx的CSS属性display
137
- * DOMUtils.css(document.querySelector("a.xx"),"display");
138
- * DOMUtils.css("a.xx","display");
139
- * > "none"
140
- * */
141
- css(
142
- element: DOMUtilsTargetElementType,
143
- property: keyof Omit<CSSStyleDeclaration, "zIndex"> | "z-index"
144
- ): string;
145
- /**
146
- * 获取元素的样式属性值
147
- * @param element 目标元素
148
- * @param property 样式属性名或包含多个属性名和属性值的对象
149
- * @example
150
- * // 获取元素a.xx的CSS属性display
151
- * DOMUtils.css(document.querySelector("a.xx"),"display");
152
- * DOMUtils.css("a.xx","display");
153
- * > "none"
154
- * */
155
- css(element: DOMUtilsTargetElementType, property: string): string;
156
- /**
157
- * 设置元素的样式属性
158
- * @param element 目标元素
159
- * @param property 样式属性名或包含多个属性名和属性值的对象
160
- * @param value 样式属性值
161
- * @example
162
- * // 设置元素a.xx的CSS属性display为block
163
- * DOMUtils.css(document.querySelector("a.xx"),"display","block");
164
- * DOMUtils.css(document.querySelector("a.xx"),"display","block !important");
165
- * DOMUtils.css("a.xx","display","block");
166
- * DOMUtils.css("a.xx","display","block !important");
167
- * @example
168
- * // 设置元素a.xx的CSS属性top为10px
169
- * DOMUtils.css(document.querySelector("a.xx"),"top","10px");
170
- * DOMUtils.css(document.querySelector("a.xx"),"top",10);
171
- * */
172
- css(
173
- element: DOMUtilsTargetElementType,
174
- property: (keyof Omit<CSSStyleDeclaration, "zIndex"> | "z-index") & string,
175
- value: string | number
176
- ): string;
177
- /**
178
- * 设置元素的样式属性
179
- * @param element 目标元素
180
- * @param property 样式属性名或包含多个属性名和属性值的对象
181
- * @param value 样式属性值
182
- * @example
183
- * // 设置元素a.xx的CSS属性display为block
184
- * DOMUtils.css(document.querySelector("a.xx"),{ display: "block" }});
185
- * DOMUtils.css(document.querySelector("a.xx"),{ display: "block !important" }});
186
- * @example
187
- * // 设置元素a.xx的CSS属性top为10px
188
- * DOMUtils.css(document.querySelector("a.xx"),{ top: "10px" });
189
- * DOMUtils.css(document.querySelector("a.xx"),{ top: 10 });
190
- * */
191
- css(
192
- element: DOMUtilsTargetElementType,
193
- property:
194
- | {
195
- [P in keyof Omit<CSSStyleDeclaration, "zIndex">]?: CSSStyleDeclaration[P];
196
- }
197
- | {
198
- "z-index": string | number;
199
- }
200
- | {
201
- [key: string]: string | number;
202
- }
203
- ): string;
204
- css(
205
- element: DOMUtilsTargetElementType,
206
- property:
207
- | keyof Omit<CSSStyleDeclaration, "zIndex">
208
- | string
209
- | {
210
- [P in keyof Omit<CSSStyleDeclaration, "zIndex">]?: string | number | CSSStyleDeclaration[P];
211
- },
212
- value?: string | number
213
- ) {
214
- let DOMUtilsContext = this;
215
- /**
216
- * 把纯数字没有px的加上
217
- */
218
- function handlePixe(propertyName: string, propertyValue: string | number) {
219
- let allowAddPixe = ["width", "height", "top", "left", "right", "bottom", "font-size"];
220
- if (typeof propertyValue === "number") {
221
- propertyValue = propertyValue.toString();
222
- }
223
- if (
224
- typeof propertyValue === "string" &&
225
- allowAddPixe.includes(propertyName) &&
226
- propertyValue.match(/[0-9]$/gi)
227
- ) {
228
- propertyValue = propertyValue + "px";
229
- }
230
- return propertyValue;
231
- }
232
- if (typeof element === "string") {
233
- element = DOMUtilsContext.selectorAll(element);
234
- }
235
- if (element == null) {
236
- return;
237
- }
238
- if (DOMUtilsCommonUtils.isNodeList(element)) {
239
- if (typeof property === "string") {
240
- if (value == null) {
241
- // 获取属性
242
- return DOMUtilsContext.css(element[0] as HTMLElement, property);
243
- } else {
244
- // 设置属性
245
- element.forEach(($ele) => {
246
- DOMUtilsContext.css($ele as HTMLElement, property);
247
- });
248
- return;
249
- }
250
- } else if (typeof property === "object") {
251
- // 设置属性
252
- element.forEach(($ele) => {
253
- DOMUtilsContext.css($ele as HTMLElement, property as object);
254
- });
255
- return;
256
- } else {
257
- }
258
- return;
259
- }
260
- let setStyleProperty = (propertyName: string, propertyValue: string | number) => {
261
- if (typeof propertyValue === "string" && propertyValue.trim().endsWith("!important")) {
262
- propertyValue = propertyValue
263
- .trim()
264
- .replace(/!important$/gi, "")
265
- .trim();
266
- element.style.setProperty(propertyName, propertyValue, "important");
267
- } else {
268
- propertyValue = handlePixe(propertyName, propertyValue);
269
- element.style.setProperty(propertyName, propertyValue);
270
- }
271
- };
272
- if (typeof property === "string") {
273
- if (value == null) {
274
- return DOMUtilsContext.windowApi.globalThis.getComputedStyle(element).getPropertyValue(property);
275
- } else {
276
- setStyleProperty(property, value);
277
- }
278
- } else if (typeof property === "object") {
279
- for (let prop in property) {
280
- let value = property[prop];
281
- setStyleProperty(prop, value!);
282
- }
283
- } else {
284
- // 其他情况
285
- throw new TypeError("property must be string or object");
286
- }
287
- }
288
- /**
289
- * 获取元素的文本内容,优先返回textContent
290
- * @param element 目标元素
291
- * @returns 如果传入了text,则返回undefined;否则返回文本内容
292
- * @example
293
- * // 设置元素a.xx的文本内容为abcd
294
- * DOMUtils.text(document.querySelector("a.xx"),"abcd")
295
- * DOMUtils.text("a.xx","abcd")
296
- * DOMUtils.text("a.xx",document.querySelector("b"))
297
- * */
298
- text(element: DOMUtilsTargetElementType | Element | DocumentFragment | Node): string;
299
- /**
300
- * 设置元素的文本内容
301
- * @param element 目标元素
302
- * @param text (可选)文本内容
303
- * @returns 如果传入了text,则返回undefined;否则返回文本内容
304
- * @example
305
- * // 设置元素a.xx的文本内容为abcd
306
- * DOMUtils.text(document.querySelector("a.xx"),"abcd")
307
- * DOMUtils.text("a.xx","abcd")
308
- * DOMUtils.text("a.xx",document.querySelector("b"))
309
- * */
310
- text(
311
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Node,
312
- text: string | HTMLElement | Element | number
313
- ): void;
314
- text(element: DOMUtilsTargetElementType | Element | DocumentFragment | Node, text?: any) {
315
- let DOMUtilsContext = this;
316
- if (typeof element === "string") {
317
- element = DOMUtilsContext.selectorAll(element);
318
- }
319
- if (element == null) {
320
- return;
321
- }
322
- if (DOMUtilsCommonUtils.isNodeList(element)) {
323
- if (text == null) {
324
- // 获取
325
- return DOMUtilsContext.text(element[0] as HTMLElement);
326
- } else {
327
- // 设置
328
- element.forEach(($ele) => {
329
- DOMUtilsContext.text($ele as HTMLElement, text);
330
- });
331
- }
332
- return;
333
- }
334
- if (text == null) {
335
- return element.textContent || (<HTMLElement>element).innerText;
336
- } else {
337
- if (text instanceof Node) {
338
- text = text.textContent || (text as HTMLElement).innerText;
339
- }
340
- if ("textContent" in element) {
341
- element.textContent = text as string;
342
- } else if ("innerText" in element) {
343
- (element as HTMLElement).innerText = text as string;
344
- }
345
- }
346
- }
382
+ /**
383
+ * 设置元素的HTML内容
384
+ * @param element 目标元素
385
+ * @param html (可选)HTML内容|元素
386
+ * @returns 如果传入了html,则返回undefined;否则返回HTML内容
387
+ * @example
388
+ * // 设置元素a.xx的文本内容为<b>abcd</b>
389
+ * DOMUtils.html(document.querySelector("a.xx"),"<b>abcd</b>")
390
+ * DOMUtils.html("a.xx","<b>abcd</b>")
391
+ * DOMUtils.html("a.xx",document.querySelector("b"))
392
+ * */
393
+ html(element: DOMUtilsTargetElementType, html: string | HTMLElement | Element | number): void;
394
+ /**
395
+ * 获取元素的HTML内容
396
+ * @param element 目标元素
397
+ * @param html (可选)HTML内容|元素
398
+ * @returns 如果传入了html,则返回undefined;否则返回HTML内容
399
+ * @example
400
+ * // 设置元素a.xx的文本内容为<b>abcd</b>
401
+ * DOMUtils.html(document.querySelector("a.xx"),"<b>abcd</b>")
402
+ * DOMUtils.html("a.xx","<b>abcd</b>")
403
+ * DOMUtils.html("a.xx",document.querySelector("b"))
404
+ * */
405
+ html(element: DOMUtilsTargetElementType): string;
406
+ html(element: DOMUtilsTargetElementType, html?: any) {
407
+ const DOMUtilsContext = this;
408
+ if (typeof element === "string") {
409
+ element = DOMUtilsContext.selectorAll(element);
410
+ }
411
+ if (element == null) {
412
+ return;
413
+ }
414
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
415
+ if (html == null) {
416
+ // 获取
417
+ return DOMUtilsContext.html(element[0] as HTMLElement);
418
+ } else {
419
+ // 设置
420
+ element.forEach(($ele) => {
421
+ DOMUtilsContext.html($ele as HTMLElement, html);
422
+ });
423
+ }
424
+ return;
425
+ }
426
+ if (html == null) {
427
+ // 获取
428
+ return element.innerHTML;
429
+ } else {
430
+ // 设置
431
+ if (html instanceof Element) {
432
+ html = html.innerHTML;
433
+ }
434
+ if ("innerHTML" in element) {
435
+ DOMUtilsCommonUtils.setSafeHTML(element, html);
436
+ }
437
+ }
438
+ }
439
+ /**
440
+ * 获取移动元素的transform偏移
441
+ */
442
+ getTransform(
443
+ element: HTMLElement,
444
+ isShow: boolean = false
445
+ ): {
446
+ transformLeft: number;
447
+ transformTop: number;
448
+ } {
449
+ const DOMUtilsContext = this;
450
+ let transform_left = 0;
451
+ let transform_top = 0;
452
+ if (!(isShow || (!isShow && DOMUtilsCommonUtils.isShow(element)))) {
453
+ /* 未显示 */
454
+ const { recovery } = DOMUtilsCommonUtils.showElement(element);
455
+ const transformInfo = DOMUtilsContext.getTransform(element, true);
456
+ recovery();
457
+ return transformInfo;
458
+ }
459
+ const elementTransform = DOMUtilsContext.windowApi.globalThis.getComputedStyle(element).transform;
460
+ if (elementTransform != null && elementTransform !== "none" && elementTransform !== "") {
461
+ const elementTransformSplit = elementTransform.match(/\((.+)\)/)?.[1].split(",");
462
+ if (elementTransformSplit) {
463
+ transform_left = Math.abs(parseInt(elementTransformSplit[4]));
464
+ transform_top = Math.abs(parseInt(elementTransformSplit[5]));
465
+ } else {
466
+ transform_left = 0;
467
+ transform_top = 0;
468
+ }
469
+ }
470
+ return {
471
+ transformLeft: transform_left,
472
+ transformTop: transform_top,
473
+ };
474
+ }
347
475
 
348
- /**
349
- * 设置元素的HTML内容
350
- * @param element 目标元素
351
- * @param html (可选)HTML内容|元素
352
- * @returns 如果传入了html,则返回undefined;否则返回HTML内容
353
- * @example
354
- * // 设置元素a.xx的文本内容为<b>abcd</b>
355
- * DOMUtils.html(document.querySelector("a.xx"),"<b>abcd</b>")
356
- * DOMUtils.html("a.xx","<b>abcd</b>")
357
- * DOMUtils.html("a.xx",document.querySelector("b"))
358
- * */
359
- html(element: DOMUtilsTargetElementType, html: string | HTMLElement | Element | number): void;
360
- /**
361
- * 获取元素的HTML内容
362
- * @param element 目标元素
363
- * @param html (可选)HTML内容|元素
364
- * @returns 如果传入了html,则返回undefined;否则返回HTML内容
365
- * @example
366
- * // 设置元素a.xx的文本内容为<b>abcd</b>
367
- * DOMUtils.html(document.querySelector("a.xx"),"<b>abcd</b>")
368
- * DOMUtils.html("a.xx","<b>abcd</b>")
369
- * DOMUtils.html("a.xx",document.querySelector("b"))
370
- * */
371
- html(element: DOMUtilsTargetElementType): string;
372
- html(element: DOMUtilsTargetElementType, html?: any) {
373
- let DOMUtilsContext = this;
374
- if (typeof element === "string") {
375
- element = DOMUtilsContext.selectorAll(element);
376
- }
377
- if (element == null) {
378
- return;
379
- }
380
- if (DOMUtilsCommonUtils.isNodeList(element)) {
381
- if (html == null) {
382
- // 获取
383
- return DOMUtilsContext.html(element[0] as HTMLElement);
384
- } else {
385
- // 设置
386
- element.forEach(($ele) => {
387
- DOMUtilsContext.html($ele as HTMLElement, html);
388
- });
389
- }
390
- return;
391
- }
392
- if (html == null) {
393
- // 获取
394
- return element.innerHTML;
395
- } else {
396
- // 设置
397
- if (html instanceof Element) {
398
- html = html.innerHTML;
399
- }
400
- if ("innerHTML" in element) {
401
- DOMUtilsCommonUtils.setSafeHTML(element, html);
402
- }
403
- }
404
- }
405
- /**
406
- * 获取移动元素的transform偏移
407
- */
408
- getTransform(
409
- element: HTMLElement,
410
- isShow: boolean = false
411
- ): {
412
- transformLeft: number;
413
- transformTop: number;
414
- } {
415
- let DOMUtilsContext = this;
416
- let transform_left = 0;
417
- let transform_top = 0;
418
- if (!(isShow || (!isShow && DOMUtilsCommonUtils.isShow(element)))) {
419
- /* 未显示 */
420
- let { recovery } = DOMUtilsCommonUtils.showElement(element);
421
- let transformInfo = DOMUtilsContext.getTransform(element, true);
422
- recovery();
423
- return transformInfo;
424
- }
425
- let elementTransform = DOMUtilsContext.windowApi.globalThis.getComputedStyle(element).transform;
426
- if (elementTransform != null && elementTransform !== "none" && elementTransform !== "") {
427
- let elementTransformSplit = elementTransform.match(/\((.+)\)/)?.[1].split(",");
428
- if (elementTransformSplit) {
429
- transform_left = Math.abs(parseInt(elementTransformSplit[4]));
430
- transform_top = Math.abs(parseInt(elementTransformSplit[5]));
431
- } else {
432
- transform_left = 0;
433
- transform_top = 0;
434
- }
435
- }
436
- return {
437
- transformLeft: transform_left,
438
- transformTop: transform_top,
439
- };
440
- }
476
+ /**
477
+ * 设置元素的value属性值
478
+ * @param element 目标元素
479
+ * @param value (可选)value属性值
480
+ * @returns 如果传入了value,则返回undefined;否则返回value属性值
481
+ * > true
482
+ * @example
483
+ * // 修改元素input.xx的复选框值为true
484
+ * DOMUtils.val(document.querySelector("input.xx"),true)
485
+ * DOMUtils.val("input.xx",true)
486
+ * */
487
+ val(
488
+ element:
489
+ | HTMLInputElement
490
+ | HTMLTextAreaElement
491
+ | HTMLSelectElement
492
+ | string
493
+ | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
494
+ | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
495
+ value: string | boolean | number
496
+ ): void;
497
+ /**
498
+ * 获取value属性值
499
+ * @param element 目标元素
500
+ * @example
501
+ * // 获取元素textarea的值
502
+ * DOMUtils.val(document.querySelector("textarea.xx"))
503
+ * */
504
+ val(
505
+ element:
506
+ | HTMLInputElement
507
+ | HTMLTextAreaElement
508
+ | HTMLSelectElement
509
+ | string
510
+ | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
511
+ | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
512
+ ): string;
513
+ /**
514
+ * 获取value属性值
515
+ * @param element 目标元素
516
+ * @example
517
+ * // 获取元素input.xx的复选框值
518
+ * DOMUtils.val(document.querySelector("input.xx"))
519
+ * DOMUtils.val("input.xx")
520
+ * */
521
+ val(
522
+ element:
523
+ | HTMLInputElement
524
+ | HTMLTextAreaElement
525
+ | HTMLSelectElement
526
+ | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
527
+ | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
528
+ ): boolean | string;
529
+ val(
530
+ element:
531
+ | HTMLInputElement
532
+ | HTMLTextAreaElement
533
+ | HTMLSelectElement
534
+ | string
535
+ | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
536
+ | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
537
+ value?: string | boolean | number
538
+ ) {
539
+ const DOMUtilsContext = this;
540
+ if (typeof element === "string") {
541
+ element = DOMUtilsContext.selectorAll(element);
542
+ }
543
+ if (element == null) {
544
+ return;
545
+ }
546
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
547
+ if (value == null) {
548
+ // 获取
549
+ return DOMUtilsContext.val(element[0] as HTMLInputElement);
550
+ } else {
551
+ // 设置
552
+ element.forEach(($ele) => {
553
+ DOMUtilsContext.val($ele as HTMLInputElement, value);
554
+ });
555
+ }
556
+ return;
557
+ }
558
+ if (value == null) {
559
+ // 获取
560
+ if (element.localName === "input" && (element.type === "checkbox" || element.type === "radio")) {
561
+ return (element as HTMLInputElement).checked;
562
+ } else {
563
+ return element.value;
564
+ }
565
+ } else {
566
+ // 设置
567
+ if (element.localName === "input" && (element.type === "checkbox" || element.type === "radio")) {
568
+ (element as HTMLInputElement).checked = !!value;
569
+ } else {
570
+ element.value = value as string;
571
+ }
572
+ }
573
+ }
441
574
 
442
- /**
443
- * 设置元素的value属性值
444
- * @param element 目标元素
445
- * @param value (可选)value属性值
446
- * @returns 如果传入了value,则返回undefined;否则返回value属性值
447
- * > true
448
- * @example
449
- * // 修改元素input.xx的复选框值为true
450
- * DOMUtils.val(document.querySelector("input.xx"),true)
451
- * DOMUtils.val("input.xx",true)
452
- * */
453
- val(
454
- element:
455
- | HTMLInputElement
456
- | HTMLTextAreaElement
457
- | HTMLSelectElement
458
- | string
459
- | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
460
- | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
461
- value: string | boolean | number
462
- ): void;
463
- /**
464
- * 获取value属性值
465
- * @param element 目标元素
466
- * @example
467
- * // 获取元素textarea的值
468
- * DOMUtils.val(document.querySelector("textarea.xx"))
469
- * */
470
- val(
471
- element:
472
- | HTMLInputElement
473
- | HTMLTextAreaElement
474
- | HTMLSelectElement
475
- | string
476
- | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
477
- | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
478
- ): string;
479
- /**
480
- * 获取value属性值
481
- * @param element 目标元素
482
- * @example
483
- * // 获取元素input.xx的复选框值
484
- * DOMUtils.val(document.querySelector("input.xx"))
485
- * DOMUtils.val("input.xx")
486
- * */
487
- val(
488
- element:
489
- | HTMLInputElement
490
- | HTMLTextAreaElement
491
- | HTMLSelectElement
492
- | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
493
- | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
494
- ): boolean | string;
495
- val(
496
- element:
497
- | HTMLInputElement
498
- | HTMLTextAreaElement
499
- | HTMLSelectElement
500
- | string
501
- | (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[]
502
- | NodeListOf<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
503
- value?: string | boolean | number
504
- ) {
505
- let DOMUtilsContext = this;
506
- if (typeof element === "string") {
507
- element = DOMUtilsContext.selectorAll(element);
508
- }
509
- if (element == null) {
510
- return;
511
- }
512
- if (DOMUtilsCommonUtils.isNodeList(element)) {
513
- if (value == null) {
514
- // 获取
515
- return DOMUtilsContext.val(element[0] as HTMLInputElement);
516
- } else {
517
- // 设置
518
- element.forEach(($ele) => {
519
- DOMUtilsContext.val($ele as HTMLInputElement, value);
520
- });
521
- }
522
- return;
523
- }
524
- if (value == null) {
525
- // 获取
526
- if (element.localName === "input" && (element.type === "checkbox" || element.type === "radio")) {
527
- return (element as HTMLInputElement).checked;
528
- } else {
529
- return element.value;
530
- }
531
- } else {
532
- // 设置
533
- if (element.localName === "input" && (element.type === "checkbox" || element.type === "radio")) {
534
- (element as HTMLInputElement).checked = !!value;
535
- } else {
536
- element.value = value as string;
537
- }
538
- }
539
- }
575
+ /**
576
+ * 获取元素的属性值
577
+ * @param element 目标元素
578
+ * @param propName 属性名
579
+ * @param propValue 属性值
580
+ * @example
581
+ * // 获取元素a.xx的属性data-value
582
+ * DOMUtils.val(document.querySelector("a.xx"),"data-value")
583
+ * DOMUtils.val("a.xx","data-value")
584
+ * > undefined
585
+ * */
586
+ prop<T>(element: DOMUtilsTargetElementType | DocumentFragment, propName: string): T;
587
+ /**
588
+ * 设置元素的属性值
589
+ * @param element 目标元素
590
+ * @param propName 属性名
591
+ * @param propValue 属性值
592
+ * @example
593
+ * // 设置元素a.xx的属性data-value为1
594
+ * DOMUtils.val(document.querySelector("a.xx"),"data-value",1)
595
+ * DOMUtils.val("a.xx","data-value",1)
596
+ * */
597
+ prop<T>(element: DOMUtilsTargetElementType | DocumentFragment, propName: string, propValue: T): void;
598
+ prop(element: DOMUtilsTargetElementType | DocumentFragment, propName: string, propValue?: any) {
599
+ const DOMUtilsContext = this;
600
+ if (typeof element === "string") {
601
+ element = DOMUtilsContext.selectorAll(element);
602
+ }
603
+ if (element == null) {
604
+ return;
605
+ }
606
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
607
+ if (propValue == null) {
608
+ // 获取
609
+ return DOMUtilsContext.prop(element[0] as HTMLElement, propName);
610
+ } else {
611
+ // 设置
612
+ element.forEach(($ele) => {
613
+ DOMUtilsContext.prop($ele as HTMLElement, propName, propValue);
614
+ });
615
+ }
616
+ return;
617
+ }
618
+ if (propValue == null) {
619
+ return Reflect.get(element, propName);
620
+ } else {
621
+ if (element instanceof Element && propName === "innerHTML") {
622
+ DOMUtilsContext.html(element, propValue);
623
+ } else {
624
+ Reflect.set(element, propName, propValue);
625
+ }
626
+ }
627
+ }
628
+ /**
629
+ * 移除元素的属性
630
+ * @param element 目标元素
631
+ * @param attrName 属性名
632
+ * @example
633
+ * // 移除元素a.xx的属性data-value
634
+ * DOMUtils.removeAttr(document.querySelector("a.xx"),"data-value")
635
+ * DOMUtils.removeAttr("a.xx","data-value")
636
+ * */
637
+ removeAttr(element: DOMUtilsTargetElementType | Element, attrName: string) {
638
+ const DOMUtilsContext = this;
639
+ if (typeof element === "string") {
640
+ element = DOMUtilsContext.selectorAll(element);
641
+ }
642
+ if (element == null) {
643
+ return;
644
+ }
645
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
646
+ // 设置
647
+ element.forEach(($ele) => {
648
+ DOMUtilsContext.removeAttr($ele as HTMLElement, attrName);
649
+ });
650
+ return;
651
+ }
652
+ element.removeAttribute(attrName);
653
+ }
654
+ /**
655
+ * 移除元素class名
656
+ * @param element 目标元素
657
+ * @param className 类名
658
+ * @example
659
+ * // 移除元素a.xx的className为xx
660
+ * DOMUtils.removeClass(document.querySelector("a.xx"),"xx")
661
+ * DOMUtils.removeClass("a.xx","xx")
662
+ */
663
+ removeClass(element: DOMUtilsTargetElementType | Element, className?: string | string[] | undefined | null) {
664
+ const DOMUtilsContext = this;
665
+ if (typeof element === "string") {
666
+ element = DOMUtilsContext.selectorAll(element);
667
+ }
668
+ if (element == null) {
669
+ return;
670
+ }
671
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
672
+ // 设置
673
+ element.forEach(($ele) => {
674
+ DOMUtilsContext.removeClass($ele as HTMLElement, className);
675
+ });
676
+ return;
677
+ }
678
+ if (className == null) {
679
+ // 清空全部className
680
+ element.className = "";
681
+ } else {
682
+ if (!Array.isArray(className)) {
683
+ className = className.trim().split(" ");
684
+ }
685
+ className.forEach((itemClassName) => {
686
+ element.classList.remove(itemClassName);
687
+ });
688
+ }
689
+ }
690
+ /**
691
+ * 移除元素的属性
692
+ * @param element 目标元素
693
+ * @param propName 属性名
694
+ * @example
695
+ * // 移除元素a.xx的href属性
696
+ * DOMUtils.removeProp(document.querySelector("a.xx"),"href")
697
+ * DOMUtils.removeProp("a.xx","href")
698
+ * */
699
+ removeProp(element: DOMUtilsTargetElementType | DocumentFragment, propName: string) {
700
+ const DOMUtilsContext = this;
701
+ if (typeof element === "string") {
702
+ element = DOMUtilsContext.selectorAll(element);
703
+ }
704
+ if (element == null) {
705
+ return;
706
+ }
707
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
708
+ // 设置
709
+ element.forEach(($ele) => {
710
+ DOMUtilsContext.removeProp($ele as HTMLElement, propName);
711
+ });
712
+ return;
713
+ }
714
+ DOMUtilsCommonUtils.delete(element, propName);
715
+ }
716
+ /**
717
+ * 将一个元素替换为另一个元素
718
+ * @param element 目标元素
719
+ * @param newElement 新元素
720
+ * @example
721
+ * // 替换元素a.xx为b.xx
722
+ * DOMUtils.replaceWith(document.querySelector("a.xx"),document.querySelector("b.xx"))
723
+ * DOMUtils.replaceWith("a.xx",'<b class="xx"></b>')
724
+ */
725
+ replaceWith(element: DOMUtilsTargetElementType, newElement: HTMLElement | string | Node) {
726
+ const DOMUtilsContext = this;
727
+ if (typeof element === "string") {
728
+ element = DOMUtilsContext.selectorAll(element);
729
+ }
730
+ if (element == null) {
731
+ return;
732
+ }
733
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
734
+ // 设置
735
+ element.forEach(($ele) => {
736
+ DOMUtilsContext.replaceWith($ele as HTMLElement, newElement);
737
+ });
738
+ return;
739
+ }
740
+ if (typeof newElement === "string") {
741
+ newElement = DOMUtilsContext.parseHTML(newElement, false, false);
742
+ }
743
+ const $parent = element.parentElement;
744
+ if ($parent) {
745
+ $parent.replaceChild(newElement as Node, element);
746
+ } else {
747
+ DOMUtilsContext.after(element, newElement as HTMLElement);
748
+ element.remove();
749
+ }
750
+ }
751
+ /**
752
+ * 给元素添加class
753
+ * @param element 目标元素
754
+ * @param className class名
755
+ * @example
756
+ * // 元素a.xx的className添加_vue_
757
+ * DOMUtils.addClass(document.querySelector("a.xx"),"_vue_")
758
+ * DOMUtils.addClass("a.xx","_vue_")
759
+ * */
760
+ addClass(element: DOMUtilsTargetElementType | Element, className: string | string[]) {
761
+ const DOMUtilsContext = this;
762
+ if (typeof element === "string") {
763
+ element = DOMUtilsContext.selectorAll(element);
764
+ }
765
+ if (element == null) {
766
+ return;
767
+ }
768
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
769
+ // 设置
770
+ element.forEach(($ele) => {
771
+ DOMUtilsContext.addClass($ele as HTMLElement, className);
772
+ });
773
+ return;
774
+ }
775
+ if (!Array.isArray(className)) {
776
+ className = className.split(" ");
777
+ }
778
+ className.forEach((itemClassName) => {
779
+ if (itemClassName.trim() == "") {
780
+ return;
781
+ }
782
+ element.classList.add(itemClassName);
783
+ });
784
+ }
785
+ /**
786
+ * 判断元素是否存在className
787
+ * @param element
788
+ * @param className
789
+ */
790
+ hasClass(element: DOMUtilsTargetElementType | Element, className: string | string[]): boolean {
791
+ const DOMUtilsContext = this;
792
+ if (typeof element === "string") {
793
+ element = DOMUtilsContext.selectorAll(element);
794
+ }
795
+ if (element == null) {
796
+ return false;
797
+ }
798
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
799
+ let flag = true;
800
+ for (let index = 0; index < element.length; index++) {
801
+ const $ele = element[index] as HTMLElement;
802
+ flag = flag && DOMUtilsContext.hasClass($ele, className);
803
+ }
804
+ return flag;
805
+ }
806
+ if (!element?.classList) {
807
+ return false;
808
+ }
809
+ if (!Array.isArray(className)) {
810
+ className = className.split(" ");
811
+ }
812
+ for (let index = 0; index < className.length; index++) {
813
+ const item = className[index].trim();
814
+ if (!element.classList.contains(item)) {
815
+ return false;
816
+ }
817
+ }
818
+ return true;
819
+ }
820
+ /**
821
+ * 函数在元素内部末尾添加子元素或HTML字符串
822
+ * @param element 目标元素
823
+ * @param content 子元素或HTML字符串
824
+ * @example
825
+ * // 元素a.xx的内部末尾添加一个元素
826
+ * DOMUtils.append(document.querySelector("a.xx"),document.querySelector("b.xx"))
827
+ * DOMUtils.append("a.xx","'<b class="xx"></b>")
828
+ * */
829
+ append(
830
+ element: DOMUtilsTargetElementType | DocumentFragment,
831
+ content: HTMLElement | string | (HTMLElement | string | Element)[] | NodeList
832
+ ) {
833
+ const DOMUtilsContext = this;
834
+ if (typeof element === "string") {
835
+ element = DOMUtilsContext.selectorAll(element);
836
+ }
837
+ if (element == null) {
838
+ return;
839
+ }
540
840
 
541
- /**
542
- * 获取元素的属性值
543
- * @param element 目标元素
544
- * @param propName 属性名
545
- * @param propValue 属性值
546
- * @example
547
- * // 获取元素a.xx的属性data-value
548
- * DOMUtils.val(document.querySelector("a.xx"),"data-value")
549
- * DOMUtils.val("a.xx","data-value")
550
- * > undefined
551
- * */
552
- prop<T extends any>(element: DOMUtilsTargetElementType | DocumentFragment, propName: string): T;
553
- /**
554
- * 设置元素的属性值
555
- * @param element 目标元素
556
- * @param propName 属性名
557
- * @param propValue 属性值
558
- * @example
559
- * // 设置元素a.xx的属性data-value为1
560
- * DOMUtils.val(document.querySelector("a.xx"),"data-value",1)
561
- * DOMUtils.val("a.xx","data-value",1)
562
- * */
563
- prop<T extends any>(
564
- element: DOMUtilsTargetElementType | DocumentFragment,
565
- propName: string,
566
- propValue: T
567
- ): void;
568
- prop(element: DOMUtilsTargetElementType | DocumentFragment, propName: string, propValue?: any) {
569
- let DOMUtilsContext = this;
570
- if (typeof element === "string") {
571
- element = DOMUtilsContext.selectorAll(element);
572
- }
573
- if (element == null) {
574
- return;
575
- }
576
- if (DOMUtilsCommonUtils.isNodeList(element)) {
577
- if (propValue == null) {
578
- // 获取
579
- return DOMUtilsContext.prop(element[0] as HTMLElement, propName);
580
- } else {
581
- // 设置
582
- element.forEach(($ele) => {
583
- DOMUtilsContext.prop($ele as HTMLElement, propName, propValue);
584
- });
585
- }
586
- return;
587
- }
588
- if (propValue == null) {
589
- return Reflect.get(element, propName);
590
- } else {
591
- if (element instanceof Element && propName === "innerHTML") {
592
- DOMUtilsContext.html(element, propValue);
593
- } else {
594
- Reflect.set(element, propName, propValue);
595
- }
596
- }
597
- }
598
- /**
599
- * 移除元素的属性
600
- * @param element 目标元素
601
- * @param attrName 属性名
602
- * @example
603
- * // 移除元素a.xx的属性data-value
604
- * DOMUtils.removeAttr(document.querySelector("a.xx"),"data-value")
605
- * DOMUtils.removeAttr("a.xx","data-value")
606
- * */
607
- removeAttr(element: DOMUtilsTargetElementType | Element, attrName: string) {
608
- let DOMUtilsContext = this;
609
- if (typeof element === "string") {
610
- element = DOMUtilsContext.selectorAll(element);
611
- }
612
- if (element == null) {
613
- return;
614
- }
615
- if (DOMUtilsCommonUtils.isNodeList(element)) {
616
- // 设置
617
- element.forEach(($ele) => {
618
- DOMUtilsContext.removeAttr($ele as HTMLElement, attrName);
619
- });
620
- return;
621
- }
622
- element.removeAttribute(attrName);
623
- }
624
- /**
625
- * 移除元素class名
626
- * @param element 目标元素
627
- * @param className 类名
628
- * @example
629
- * // 移除元素a.xx的className为xx
630
- * DOMUtils.removeClass(document.querySelector("a.xx"),"xx")
631
- * DOMUtils.removeClass("a.xx","xx")
632
- */
633
- removeClass(
634
- element: DOMUtilsTargetElementType | Element,
635
- className?: string | string[] | undefined | null
636
- ) {
637
- let DOMUtilsContext = this;
638
- if (typeof element === "string") {
639
- element = DOMUtilsContext.selectorAll(element);
640
- }
641
- if (element == null) {
642
- return;
643
- }
644
- if (DOMUtilsCommonUtils.isNodeList(element)) {
645
- // 设置
646
- element.forEach(($ele) => {
647
- DOMUtilsContext.removeClass($ele as HTMLElement, className);
648
- });
649
- return;
650
- }
651
- if (className == null) {
652
- // 清空全部className
653
- element.className = "";
654
- } else {
655
- if (!Array.isArray(className)) {
656
- className = className.split(" ");
657
- }
658
- className.forEach((itemClassName) => {
659
- element.classList.remove(itemClassName);
660
- });
661
- }
662
- }
663
- /**
664
- * 移除元素的属性
665
- * @param element 目标元素
666
- * @param propName 属性名
667
- * @example
668
- * // 移除元素a.xx的href属性
669
- * DOMUtils.removeProp(document.querySelector("a.xx"),"href")
670
- * DOMUtils.removeProp("a.xx","href")
671
- * */
672
- removeProp(element: DOMUtilsTargetElementType | DocumentFragment, propName: string) {
673
- let DOMUtilsContext = this;
674
- if (typeof element === "string") {
675
- element = DOMUtilsContext.selectorAll(element);
676
- }
677
- if (element == null) {
678
- return;
679
- }
680
- if (DOMUtilsCommonUtils.isNodeList(element)) {
681
- // 设置
682
- element.forEach(($ele) => {
683
- DOMUtilsContext.removeProp($ele as HTMLElement, propName);
684
- });
685
- return;
686
- }
687
- DOMUtilsCommonUtils.delete(element, propName);
688
- }
689
- /**
690
- * 将一个元素替换为另一个元素
691
- * @param element 目标元素
692
- * @param newElement 新元素
693
- * @example
694
- * // 替换元素a.xx为b.xx
695
- * DOMUtils.replaceWith(document.querySelector("a.xx"),document.querySelector("b.xx"))
696
- * DOMUtils.replaceWith("a.xx",'<b class="xx"></b>')
697
- */
698
- replaceWith(element: DOMUtilsTargetElementType, newElement: HTMLElement | string | Node) {
699
- let DOMUtilsContext = this;
700
- if (typeof element === "string") {
701
- element = DOMUtilsContext.selectorAll(element);
702
- }
703
- if (element == null) {
704
- return;
705
- }
706
- if (DOMUtilsCommonUtils.isNodeList(element)) {
707
- // 设置
708
- element.forEach(($ele) => {
709
- DOMUtilsContext.replaceWith($ele as HTMLElement, newElement);
710
- });
711
- return;
712
- }
713
- if (typeof newElement === "string") {
714
- newElement = DOMUtilsContext.parseHTML(newElement, false, false);
715
- }
716
- let $parent = element.parentElement;
717
- if ($parent) {
718
- $parent.replaceChild(newElement as Node, element);
719
- } else {
720
- DOMUtilsContext.after(element, newElement as HTMLElement);
721
- element.remove();
722
- }
723
- }
724
- /**
725
- * 给元素添加class
726
- * @param element 目标元素
727
- * @param className class名
728
- * @example
729
- * // 元素a.xx的className添加_vue_
730
- * DOMUtils.addClass(document.querySelector("a.xx"),"_vue_")
731
- * DOMUtils.addClass("a.xx","_vue_")
732
- * */
733
- addClass(element: DOMUtilsTargetElementType | Element, className: string | string[]) {
734
- let DOMUtilsContext = this;
735
- if (typeof element === "string") {
736
- element = DOMUtilsContext.selectorAll(element);
737
- }
738
- if (element == null) {
739
- return;
740
- }
741
- if (DOMUtilsCommonUtils.isNodeList(element)) {
742
- // 设置
743
- element.forEach(($ele) => {
744
- DOMUtilsContext.addClass($ele as HTMLElement, className);
745
- });
746
- return;
747
- }
748
- if (!Array.isArray(className)) {
749
- className = className.split(" ");
750
- }
751
- className.forEach((itemClassName) => {
752
- if (itemClassName.trim() == "") {
753
- return;
754
- }
755
- element.classList.add(itemClassName);
756
- });
757
- }
758
- /**
759
- * 判断元素是否存在className
760
- * @param element
761
- * @param className
762
- */
763
- hasClass(element: DOMUtilsTargetElementType | Element, className: string | string[]): boolean {
764
- let DOMUtilsContext = this;
765
- if (typeof element === "string") {
766
- element = DOMUtilsContext.selectorAll(element);
767
- }
768
- if (element == null) {
769
- return false;
770
- }
771
- if (DOMUtilsCommonUtils.isNodeList(element)) {
772
- let flag = true;
773
- for (let index = 0; index < element.length; index++) {
774
- const $ele = element[index] as HTMLElement;
775
- flag = flag && DOMUtilsContext.hasClass($ele, className);
776
- }
777
- return flag;
778
- }
779
- if (!element?.classList) {
780
- return false;
781
- }
782
- if (!Array.isArray(className)) {
783
- className = className.split(" ");
784
- }
785
- for (let index = 0; index < className.length; index++) {
786
- const item = className[index].trim();
787
- if (!element.classList.contains(item)) {
788
- return false;
789
- }
790
- }
791
- return true;
792
- }
793
- /**
794
- * 函数在元素内部末尾添加子元素或HTML字符串
795
- * @param element 目标元素
796
- * @param content 子元素或HTML字符串
797
- * @example
798
- * // 元素a.xx的内部末尾添加一个元素
799
- * DOMUtils.append(document.querySelector("a.xx"),document.querySelector("b.xx"))
800
- * DOMUtils.append("a.xx","'<b class="xx"></b>")
801
- * */
802
- append(
803
- element: DOMUtilsTargetElementType | DocumentFragment,
804
- content: HTMLElement | string | (HTMLElement | string | Element)[] | NodeList
805
- ) {
806
- let DOMUtilsContext = this;
807
- if (typeof element === "string") {
808
- element = DOMUtilsContext.selectorAll(element);
809
- }
810
- if (element == null) {
811
- return;
812
- }
841
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
842
+ // 设置
843
+ element.forEach(($ele) => {
844
+ DOMUtilsContext.append($ele as HTMLElement, content);
845
+ });
846
+ return;
847
+ }
848
+ function elementAppendChild(ele: HTMLElement | DocumentFragment, text: HTMLElement | string) {
849
+ if (typeof content === "string") {
850
+ if (ele instanceof DocumentFragment) {
851
+ if (typeof text === "string") {
852
+ text = DOMUtilsContext.parseHTML(text, true, false);
853
+ }
854
+ ele.appendChild(text);
855
+ } else {
856
+ ele.insertAdjacentHTML("beforeend", DOMUtilsCommonUtils.getSafeHTML(text as string));
857
+ }
858
+ } else {
859
+ ele.appendChild(text as HTMLElement);
860
+ }
861
+ }
862
+ if (Array.isArray(content) || content instanceof NodeList) {
863
+ /* 数组 */
864
+ const fragment = DOMUtilsContext.windowApi.document.createDocumentFragment();
865
+ content.forEach((ele) => {
866
+ if (typeof ele === "string") {
867
+ // 转为元素
868
+ ele = DOMUtilsContext.parseHTML(ele, true, false);
869
+ }
870
+ fragment.appendChild(ele);
871
+ });
872
+ element.appendChild(fragment);
873
+ } else {
874
+ elementAppendChild(element, content);
875
+ }
876
+ }
877
+ /**
878
+ * 函数 在元素内部开头添加子元素或HTML字符串
879
+ * @param element 目标元素
880
+ * @param content 子元素或HTML字符串
881
+ * @example
882
+ * // 元素a.xx内部开头添加一个元素
883
+ * DOMUtils.prepend(document.querySelector("a.xx"),document.querySelector("b.xx"))
884
+ * DOMUtils.prepend("a.xx","'<b class="xx"></b>")
885
+ * */
886
+ prepend(element: DOMUtilsTargetElementType | DocumentFragment, content: HTMLElement | string) {
887
+ const DOMUtilsContext = this;
888
+ if (typeof element === "string") {
889
+ element = DOMUtilsContext.selectorAll(element);
890
+ }
891
+ if (element == null) {
892
+ return;
893
+ }
894
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
895
+ // 设置
896
+ element.forEach(($ele) => {
897
+ DOMUtilsContext.prepend($ele as HTMLElement, content);
898
+ });
899
+ return;
900
+ }
901
+ if (typeof content === "string") {
902
+ if (element instanceof DocumentFragment) {
903
+ content = DOMUtilsContext.parseHTML(content, true, false);
904
+ element.prepend(content);
905
+ } else {
906
+ element.insertAdjacentHTML("afterbegin", DOMUtilsCommonUtils.getSafeHTML(content));
907
+ }
908
+ } else {
909
+ const $firstChild = element.firstChild;
910
+ if ($firstChild == null) {
911
+ element.prepend(content);
912
+ } else {
913
+ element.insertBefore(content, element.firstChild);
914
+ }
915
+ }
916
+ }
917
+ /**
918
+ * 在元素后面添加兄弟元素或HTML字符串
919
+ * @param element 目标元素
920
+ * @param content 兄弟元素或HTML字符串
921
+ * @example
922
+ * // 元素a.xx后面添加一个元素
923
+ * DOMUtils.after(document.querySelector("a.xx"),document.querySelector("b.xx"))
924
+ * DOMUtils.after("a.xx","'<b class="xx"></b>")
925
+ * */
926
+ after(element: DOMUtilsTargetElementType, content: HTMLElement | string) {
927
+ const DOMUtilsContext = this;
928
+ if (typeof element === "string") {
929
+ element = DOMUtilsContext.selectorAll(element);
930
+ }
931
+ if (element == null) {
932
+ return;
933
+ }
934
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
935
+ // 设置
936
+ element.forEach(($ele) => {
937
+ DOMUtilsContext.after($ele as HTMLElement, content);
938
+ });
939
+ return;
940
+ }
941
+ if (typeof content === "string") {
942
+ element.insertAdjacentHTML("afterend", DOMUtilsCommonUtils.getSafeHTML(content));
943
+ } else {
944
+ const $parent = element.parentElement;
945
+ const $nextSlibling = element.nextSibling;
946
+ if (!$parent || $nextSlibling) {
947
+ // 任意一个不行
948
+ element.after(content);
949
+ } else {
950
+ element!.parentElement!.insertBefore(content, element.nextSibling);
951
+ }
952
+ }
953
+ }
954
+ /**
955
+ * 在元素前面添加兄弟元素或HTML字符串
956
+ * @param element 目标元素
957
+ * @param content 兄弟元素或HTML字符串
958
+ * @example
959
+ * // 元素a.xx前面添加一个元素
960
+ * DOMUtils.before(document.querySelector("a.xx"),document.querySelector("b.xx"))
961
+ * DOMUtils.before("a.xx","'<b class="xx"></b>")
962
+ * */
963
+ before(element: DOMUtilsTargetElementType, content: HTMLElement | string) {
964
+ const DOMUtilsContext = this;
965
+ if (typeof element === "string") {
966
+ element = DOMUtilsContext.selectorAll(element);
967
+ }
968
+ if (element == null) {
969
+ return;
970
+ }
971
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
972
+ // 设置
973
+ element.forEach(($ele) => {
974
+ DOMUtilsContext.before($ele as HTMLElement, content);
975
+ });
976
+ return;
977
+ }
978
+ if (typeof content === "string") {
979
+ element.insertAdjacentHTML("beforebegin", DOMUtilsCommonUtils.getSafeHTML(content));
980
+ } else {
981
+ const $parent = element.parentElement;
982
+ if (!$parent) {
983
+ element.before(content);
984
+ } else {
985
+ $parent.insertBefore(content, element);
986
+ }
987
+ }
988
+ }
989
+ /**
990
+ * 移除元素
991
+ * @param element 目标元素
992
+ * @example
993
+ * // 元素a.xx前面添加一个元素
994
+ * DOMUtils.remove(document.querySelector("a.xx"))
995
+ * DOMUtils.remove(document.querySelectorAll("a.xx"))
996
+ * DOMUtils.remove("a.xx")
997
+ * */
998
+ remove(element: DOMUtilsTargetElementType | Element) {
999
+ const DOMUtilsContext = this;
1000
+ if (typeof element === "string") {
1001
+ element = DOMUtilsContext.selectorAll(element);
1002
+ }
1003
+ if (element == null) {
1004
+ return;
1005
+ }
1006
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1007
+ element.forEach(($ele) => {
1008
+ DOMUtilsContext.remove($ele as HTMLElement);
1009
+ });
1010
+ return;
1011
+ }
1012
+ if (typeof element.remove === "function") {
1013
+ element.remove();
1014
+ } else if (element.parentElement) {
1015
+ element.parentElement.removeChild(element);
1016
+ } else if (element.parentNode) {
1017
+ element.parentNode.removeChild(element);
1018
+ }
1019
+ }
1020
+ /**
1021
+ * 移除元素的所有子元素
1022
+ * @param element 目标元素
1023
+ * @example
1024
+ * // 移除元素a.xx元素的所有子元素
1025
+ * DOMUtils.empty(document.querySelector("a.xx"))
1026
+ * DOMUtils.empty("a.xx")
1027
+ * */
1028
+ empty(element: DOMUtilsTargetElementType | Element) {
1029
+ const DOMUtilsContext = this;
1030
+ if (typeof element === "string") {
1031
+ element = DOMUtilsContext.selectorAll(element);
1032
+ }
1033
+ if (element == null) {
1034
+ return;
1035
+ }
1036
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1037
+ // 设置
1038
+ element.forEach(($ele) => {
1039
+ DOMUtilsContext.empty($ele as HTMLElement);
1040
+ });
1041
+ return;
1042
+ }
1043
+ if (element.innerHTML) {
1044
+ element.innerHTML = "";
1045
+ } else if (element.textContent) {
1046
+ element.textContent = "";
1047
+ }
1048
+ }
1049
+ /**
1050
+ * 获取元素相对于文档的偏移坐标(加上文档的滚动条)
1051
+ * @param element 目标元素
1052
+ * @example
1053
+ * // 获取元素a.xx的对于文档的偏移坐标
1054
+ * DOMUtils.offset(document.querySelector("a.xx"))
1055
+ * DOMUtils.offset("a.xx")
1056
+ * > 0
1057
+ */
1058
+ offset(element: HTMLElement | string) {
1059
+ const DOMUtilsContext = this;
1060
+ if (typeof element === "string") {
1061
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1062
+ }
1063
+ if (element == null) {
1064
+ return;
1065
+ }
813
1066
 
814
- if (DOMUtilsCommonUtils.isNodeList(element)) {
815
- // 设置
816
- element.forEach(($ele) => {
817
- DOMUtilsContext.append($ele as HTMLElement, content);
818
- });
819
- return;
820
- }
821
- function elementAppendChild(ele: HTMLElement | DocumentFragment, text: HTMLElement | string) {
822
- if (typeof content === "string") {
823
- if (ele instanceof DocumentFragment) {
824
- if (typeof text === "string") {
825
- text = DOMUtilsContext.parseHTML(text, true, false);
826
- }
827
- ele.appendChild(text);
828
- } else {
829
- ele.insertAdjacentHTML("beforeend", DOMUtilsCommonUtils.getSafeHTML(text as string));
830
- }
831
- } else {
832
- ele.appendChild(text as HTMLElement);
833
- }
834
- }
835
- if (Array.isArray(content) || content instanceof NodeList) {
836
- /* 数组 */
837
- let fragment = DOMUtilsContext.windowApi.document.createDocumentFragment();
838
- content.forEach((ele) => {
839
- if (typeof ele === "string") {
840
- // 转为元素
841
- ele = DOMUtilsContext.parseHTML(ele, true, false);
842
- }
843
- fragment.appendChild(ele);
844
- });
845
- element.appendChild(fragment);
846
- } else {
847
- elementAppendChild(element, content);
848
- }
849
- }
850
- /**
851
- * 函数 在元素内部开头添加子元素或HTML字符串
852
- * @param element 目标元素
853
- * @param content 子元素或HTML字符串
854
- * @example
855
- * // 元素a.xx内部开头添加一个元素
856
- * DOMUtils.prepend(document.querySelector("a.xx"),document.querySelector("b.xx"))
857
- * DOMUtils.prepend("a.xx","'<b class="xx"></b>")
858
- * */
859
- prepend(element: DOMUtilsTargetElementType | DocumentFragment, content: HTMLElement | string) {
860
- let DOMUtilsContext = this;
861
- if (typeof element === "string") {
862
- element = DOMUtilsContext.selectorAll(element);
863
- }
864
- if (element == null) {
865
- return;
866
- }
867
- if (DOMUtilsCommonUtils.isNodeList(element)) {
868
- // 设置
869
- element.forEach(($ele) => {
870
- DOMUtilsContext.prepend($ele as HTMLElement, content);
871
- });
872
- return;
873
- }
874
- if (typeof content === "string") {
875
- if (element instanceof DocumentFragment) {
876
- content = DOMUtilsContext.parseHTML(content, true, false);
877
- element.prepend(content);
878
- } else {
879
- element.insertAdjacentHTML("afterbegin", DOMUtilsCommonUtils.getSafeHTML(content));
880
- }
881
- } else {
882
- let $firstChild = element.firstChild;
883
- if ($firstChild == null) {
884
- element.prepend(content);
885
- } else {
886
- element.insertBefore(content, element.firstChild);
887
- }
888
- }
889
- }
890
- /**
891
- * 在元素后面添加兄弟元素或HTML字符串
892
- * @param element 目标元素
893
- * @param content 兄弟元素或HTML字符串
894
- * @example
895
- * // 元素a.xx后面添加一个元素
896
- * DOMUtils.after(document.querySelector("a.xx"),document.querySelector("b.xx"))
897
- * DOMUtils.after("a.xx","'<b class="xx"></b>")
898
- * */
899
- after(element: DOMUtilsTargetElementType, content: HTMLElement | string) {
900
- let DOMUtilsContext = this;
901
- if (typeof element === "string") {
902
- element = DOMUtilsContext.selectorAll(element);
903
- }
904
- if (element == null) {
905
- return;
906
- }
907
- if (DOMUtilsCommonUtils.isNodeList(element)) {
908
- // 设置
909
- element.forEach(($ele) => {
910
- DOMUtilsContext.after($ele as HTMLElement, content);
911
- });
912
- return;
913
- }
914
- if (typeof content === "string") {
915
- element.insertAdjacentHTML("afterend", DOMUtilsCommonUtils.getSafeHTML(content));
916
- } else {
917
- let $parent = element.parentElement;
918
- let $nextSlibling = element.nextSibling;
919
- if (!$parent || $nextSlibling) {
920
- // 任意一个不行
921
- element.after(content);
922
- } else {
923
- element!.parentElement!.insertBefore(content, element.nextSibling);
924
- }
925
- }
926
- }
927
- /**
928
- * 在元素前面添加兄弟元素或HTML字符串
929
- * @param element 目标元素
930
- * @param content 兄弟元素或HTML字符串
931
- * @example
932
- * // 元素a.xx前面添加一个元素
933
- * DOMUtils.before(document.querySelector("a.xx"),document.querySelector("b.xx"))
934
- * DOMUtils.before("a.xx","'<b class="xx"></b>")
935
- * */
936
- before(element: DOMUtilsTargetElementType, content: HTMLElement | string) {
937
- let DOMUtilsContext = this;
938
- if (typeof element === "string") {
939
- element = DOMUtilsContext.selectorAll(element);
940
- }
941
- if (element == null) {
942
- return;
943
- }
944
- if (DOMUtilsCommonUtils.isNodeList(element)) {
945
- // 设置
946
- element.forEach(($ele) => {
947
- DOMUtilsContext.before($ele as HTMLElement, content);
948
- });
949
- return;
950
- }
951
- if (typeof content === "string") {
952
- element.insertAdjacentHTML("beforebegin", DOMUtilsCommonUtils.getSafeHTML(content));
953
- } else {
954
- let $parent = element.parentElement;
955
- if (!$parent) {
956
- element.before(content);
957
- } else {
958
- $parent.insertBefore(content, element);
959
- }
960
- }
961
- }
962
- /**
963
- * 移除元素
964
- * @param element 目标元素
965
- * @example
966
- * // 元素a.xx前面添加一个元素
967
- * DOMUtils.remove(document.querySelector("a.xx"))
968
- * DOMUtils.remove(document.querySelectorAll("a.xx"))
969
- * DOMUtils.remove("a.xx")
970
- * */
971
- remove(element: DOMUtilsTargetElementType | Element) {
972
- let DOMUtilsContext = this;
973
- if (typeof element === "string") {
974
- element = DOMUtilsContext.selectorAll(element);
975
- }
976
- if (element == null) {
977
- return;
978
- }
979
- if (DOMUtilsCommonUtils.isNodeList(element)) {
980
- element.forEach(($ele) => {
981
- DOMUtilsContext.remove($ele as HTMLElement);
982
- });
983
- return;
984
- }
985
- if (typeof element.remove === "function") {
986
- element.remove();
987
- } else if (element.parentElement) {
988
- element.parentElement.removeChild(element);
989
- } else if (element.parentNode) {
990
- element.parentNode.removeChild(element);
991
- }
992
- }
993
- /**
994
- * 移除元素的所有子元素
995
- * @param element 目标元素
996
- * @example
997
- * // 移除元素a.xx元素的所有子元素
998
- * DOMUtils.empty(document.querySelector("a.xx"))
999
- * DOMUtils.empty("a.xx")
1000
- * */
1001
- empty(element: DOMUtilsTargetElementType | Element) {
1002
- let DOMUtilsContext = this;
1003
- if (typeof element === "string") {
1004
- element = DOMUtilsContext.selectorAll(element);
1005
- }
1006
- if (element == null) {
1007
- return;
1008
- }
1009
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1010
- // 设置
1011
- element.forEach(($ele) => {
1012
- DOMUtilsContext.empty($ele as HTMLElement);
1013
- });
1014
- return;
1015
- }
1016
- if (element.innerHTML) {
1017
- element.innerHTML = "";
1018
- } else if (element.textContent) {
1019
- element.textContent = "";
1020
- }
1021
- }
1022
- /**
1023
- * 获取元素相对于文档的偏移坐标(加上文档的滚动条)
1024
- * @param element 目标元素
1025
- * @example
1026
- * // 获取元素a.xx的对于文档的偏移坐标
1027
- * DOMUtils.offset(document.querySelector("a.xx"))
1028
- * DOMUtils.offset("a.xx")
1029
- * > 0
1030
- */
1031
- offset(element: HTMLElement | string) {
1032
- let DOMUtilsContext = this;
1033
- if (typeof element === "string") {
1034
- element = DOMUtilsContext.selector(element) as HTMLElement;
1035
- }
1036
- if (element == null) {
1037
- return;
1038
- }
1067
+ const rect = element.getBoundingClientRect();
1068
+ return {
1069
+ /** y轴偏移 */
1070
+ top: rect.top + DOMUtilsContext.windowApi.globalThis.scrollY,
1071
+ /** x轴偏移 */
1072
+ left: rect.left + DOMUtilsContext.windowApi.globalThis.scrollX,
1073
+ };
1074
+ }
1075
+ /**
1076
+ * 获取元素的宽度
1077
+ * @param element 要获取宽度的元素
1078
+ * @param value 宽度值
1079
+ * @param isShow 是否已进行isShow,避免爆堆栈
1080
+ * @returns 元素的宽度,单位为像素
1081
+ * @example
1082
+ * // 获取元素a.xx的宽度
1083
+ * DOMUtils.width(document.querySelector("a.xx"))
1084
+ * DOMUtils.width("a.xx")
1085
+ * > 100
1086
+ * // 获取window的宽度
1087
+ * DOMUtils.width(window)
1088
+ * > 400
1089
+ * @example
1090
+ * // 设置元素a.xx的宽度为200
1091
+ * DOMUtils.width(document.querySelector("a.xx"),200)
1092
+ * DOMUtils.width("a.xx",200)
1093
+ */
1094
+ width(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1095
+ width(element: HTMLElement | string | Window | typeof globalThis | Document, isShow: boolean = false): number {
1096
+ const DOMUtilsContext = this;
1097
+ if (typeof element === "string") {
1098
+ element = DOMUtilsContext.selector<HTMLElement>(element)!;
1099
+ }
1100
+ if (DOMUtilsCommonUtils.isWin(element)) {
1101
+ return DOMUtilsContext.windowApi.window.document.documentElement.clientWidth;
1102
+ }
1103
+ if ((element as HTMLElement).nodeType === 9) {
1104
+ /* Document文档节点 */
1105
+ element = element as Document;
1106
+ return Math.max(
1107
+ element.body.scrollWidth,
1108
+ element.documentElement.scrollWidth,
1109
+ element.body.offsetWidth,
1110
+ element.documentElement.offsetWidth,
1111
+ element.documentElement.clientWidth
1112
+ );
1113
+ }
1114
+ if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element as HTMLElement))) {
1115
+ /* 已显示 */
1116
+ /* 不从style中获取对应的宽度,因为可能使用了class定义了width !important */
1117
+ element = element as HTMLElement;
1118
+ /* 如果element.style.width为空 则从css里面获取是否定义了width信息如果定义了 则读取css里面定义的宽度width */
1119
+ if (parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "width").toString()) > 0) {
1120
+ return parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "width").toString());
1121
+ }
1039
1122
 
1040
- let rect = element.getBoundingClientRect();
1041
- return {
1042
- /** y轴偏移 */
1043
- top: rect.top + DOMUtilsContext.windowApi.globalThis.scrollY,
1044
- /** x轴偏移 */
1045
- left: rect.left + DOMUtilsContext.windowApi.globalThis.scrollX,
1046
- };
1047
- }
1048
- /**
1049
- * 获取元素的宽度
1050
- * @param element 要获取宽度的元素
1051
- * @param value 宽度值
1052
- * @param isShow 是否已进行isShow,避免爆堆栈
1053
- * @returns 元素的宽度,单位为像素
1054
- * @example
1055
- * // 获取元素a.xx的宽度
1056
- * DOMUtils.width(document.querySelector("a.xx"))
1057
- * DOMUtils.width("a.xx")
1058
- * > 100
1059
- * // 获取window的宽度
1060
- * DOMUtils.width(window)
1061
- * > 400
1062
- * @example
1063
- * // 设置元素a.xx的宽度为200
1064
- * DOMUtils.width(document.querySelector("a.xx"),200)
1065
- * DOMUtils.width("a.xx",200)
1066
- */
1067
- width(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1068
- width(
1069
- element: HTMLElement | string | Window | typeof globalThis | Document,
1070
- isShow: boolean = false
1071
- ): number {
1072
- let DOMUtilsContext = this;
1073
- if (typeof element === "string") {
1074
- element = DOMUtilsContext.selector<HTMLElement>(element)!;
1075
- }
1076
- if (element == null) {
1077
- // @ts-ignore
1078
- return;
1079
- }
1080
- if (DOMUtilsCommonUtils.isWin(element)) {
1081
- return DOMUtilsContext.windowApi.window.document.documentElement.clientWidth;
1082
- }
1083
- if ((element as HTMLElement).nodeType === 9) {
1084
- /* Document文档节点 */
1085
- element = element as Document;
1086
- return Math.max(
1087
- element.body.scrollWidth,
1088
- element.documentElement.scrollWidth,
1089
- element.body.offsetWidth,
1090
- element.documentElement.offsetWidth,
1091
- element.documentElement.clientWidth
1092
- );
1093
- }
1094
- if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element as HTMLElement))) {
1095
- /* 已显示 */
1096
- /* 不从style中获取对应的宽度,因为可能使用了class定义了width !important */
1097
- element = element as HTMLElement;
1098
- /* 如果element.style.width为空 则从css里面获取是否定义了width信息如果定义了 则读取css里面定义的宽度width */
1099
- if (parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "width").toString()) > 0) {
1100
- return parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "width").toString());
1101
- }
1123
+ /* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetWidth来进行计算 */
1124
+ if (element.offsetWidth > 0) {
1125
+ const borderLeftWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderLeftWidth");
1126
+ const borderRightWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderRightWidth");
1127
+ const paddingLeft = DOMUtilsCommonUtils.getStyleValue(element, "paddingLeft");
1128
+ const paddingRight = DOMUtilsCommonUtils.getStyleValue(element, "paddingRight");
1129
+ const backHeight =
1130
+ parseFloat(element.offsetWidth.toString()) -
1131
+ parseFloat(borderLeftWidth.toString()) -
1132
+ parseFloat(borderRightWidth.toString()) -
1133
+ parseFloat(paddingLeft.toString()) -
1134
+ parseFloat(paddingRight.toString());
1135
+ return parseFloat(backHeight.toString());
1136
+ }
1137
+ return 0;
1138
+ } else {
1139
+ /* 未显示 */
1140
+ element = element as HTMLElement;
1141
+ const { recovery } = DOMUtilsCommonUtils.showElement(element);
1142
+ const width = DOMUtilsContext.width(element, true);
1143
+ recovery();
1144
+ return width;
1145
+ }
1146
+ }
1102
1147
 
1103
- /* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetWidth来进行计算 */
1104
- if (element.offsetWidth > 0) {
1105
- let borderLeftWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderLeftWidth");
1106
- let borderRightWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderRightWidth");
1107
- let paddingLeft = DOMUtilsCommonUtils.getStyleValue(element, "paddingLeft");
1108
- let paddingRight = DOMUtilsCommonUtils.getStyleValue(element, "paddingRight");
1109
- let backHeight =
1110
- parseFloat(element.offsetWidth.toString()) -
1111
- parseFloat(borderLeftWidth.toString()) -
1112
- parseFloat(borderRightWidth.toString()) -
1113
- parseFloat(paddingLeft.toString()) -
1114
- parseFloat(paddingRight.toString());
1115
- return parseFloat(backHeight.toString());
1116
- }
1117
- return 0;
1118
- } else {
1119
- /* 未显示 */
1120
- element = element as HTMLElement;
1121
- let { recovery } = DOMUtilsCommonUtils.showElement(element);
1122
- let width = DOMUtilsContext.width(element, true);
1123
- recovery();
1124
- return width;
1125
- }
1126
- }
1148
+ /**
1149
+ * 获取元素的高度
1150
+ * @param element 要获取高度的元素
1151
+ * @param isShow 是否已进行isShow,避免爆堆栈
1152
+ * @returns 元素的高度,单位为像素
1153
+ * @example
1154
+ * // 获取元素a.xx的高度
1155
+ * DOMUtils.height(document.querySelector("a.xx"))
1156
+ * DOMUtils.height("a.xx")
1157
+ * > 100
1158
+ * // 获取window的高度
1159
+ * DOMUtils.height(window)
1160
+ * > 700
1161
+ * @example
1162
+ * // 设置元素a.xx的高度为200
1163
+ * DOMUtils.height(document.querySelector("a.xx"),200)
1164
+ * DOMUtils.height("a.xx",200)
1165
+ */
1166
+ height(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1167
+ height(element: HTMLElement | string | Window | typeof globalThis | Document, isShow: boolean = false): number {
1168
+ const DOMUtilsContext = this;
1169
+ if (DOMUtilsCommonUtils.isWin(element)) {
1170
+ return DOMUtilsContext.windowApi.window.document.documentElement.clientHeight;
1171
+ }
1172
+ if (typeof element === "string") {
1173
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1174
+ }
1175
+ if ((element as Document).nodeType === 9) {
1176
+ element = element as Document;
1177
+ /* Document文档节点 */
1178
+ return Math.max(
1179
+ element.body.scrollHeight,
1180
+ element.documentElement.scrollHeight,
1181
+ element.body.offsetHeight,
1182
+ element.documentElement.offsetHeight,
1183
+ element.documentElement.clientHeight
1184
+ );
1185
+ }
1186
+ if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element as HTMLElement))) {
1187
+ element = element as HTMLElement;
1188
+ /* 已显示 */
1189
+ /* 从style中获取对应的高度,因为可能使用了class定义了width !important */
1190
+ /* 如果element.style.height为空 则从css里面获取是否定义了height信息如果定义了 则读取css里面定义的高度height */
1191
+ if (parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "height").toString()) > 0) {
1192
+ return parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "height").toString());
1193
+ }
1127
1194
 
1128
- /**
1129
- * 获取元素的高度
1130
- * @param element 要获取高度的元素
1131
- * @param isShow 是否已进行isShow,避免爆堆栈
1132
- * @returns 元素的高度,单位为像素
1133
- * @example
1134
- * // 获取元素a.xx的高度
1135
- * DOMUtils.height(document.querySelector("a.xx"))
1136
- * DOMUtils.height("a.xx")
1137
- * > 100
1138
- * // 获取window的高度
1139
- * DOMUtils.height(window)
1140
- * > 700
1141
- * @example
1142
- * // 设置元素a.xx的高度为200
1143
- * DOMUtils.height(document.querySelector("a.xx"),200)
1144
- * DOMUtils.height("a.xx",200)
1145
- */
1146
- height(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1147
- height(
1148
- element: HTMLElement | string | Window | typeof globalThis | Document,
1149
- isShow: boolean = false
1150
- ): number {
1151
- let DOMUtilsContext = this;
1152
- if (DOMUtilsCommonUtils.isWin(element)) {
1153
- return DOMUtilsContext.windowApi.window.document.documentElement.clientHeight;
1154
- }
1155
- if (typeof element === "string") {
1156
- element = DOMUtilsContext.selector(element) as HTMLElement;
1157
- }
1158
- if (element == null) {
1159
- // @ts-ignore
1160
- return;
1161
- }
1162
- if ((element as Document).nodeType === 9) {
1163
- element = element as Document;
1164
- /* Document文档节点 */
1165
- return Math.max(
1166
- element.body.scrollHeight,
1167
- element.documentElement.scrollHeight,
1168
- element.body.offsetHeight,
1169
- element.documentElement.offsetHeight,
1170
- element.documentElement.clientHeight
1171
- );
1172
- }
1173
- if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element as HTMLElement))) {
1174
- element = element as HTMLElement;
1175
- /* 已显示 */
1176
- /* 从style中获取对应的高度,因为可能使用了class定义了width !important */
1177
- /* 如果element.style.height为空 则从css里面获取是否定义了height信息如果定义了 则读取css里面定义的高度height */
1178
- if (parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "height").toString()) > 0) {
1179
- return parseFloat(DOMUtilsCommonUtils.getStyleValue(element, "height").toString());
1180
- }
1195
+ /* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetHeight来进行计算 */
1196
+ if (element.offsetHeight > 0) {
1197
+ const borderTopWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderTopWidth");
1198
+ const borderBottomWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderBottomWidth");
1199
+ const paddingTop = DOMUtilsCommonUtils.getStyleValue(element, "paddingTop");
1200
+ const paddingBottom = DOMUtilsCommonUtils.getStyleValue(element, "paddingBottom");
1201
+ const backHeight =
1202
+ parseFloat(element.offsetHeight.toString()) -
1203
+ parseFloat(borderTopWidth.toString()) -
1204
+ parseFloat(borderBottomWidth.toString()) -
1205
+ parseFloat(paddingTop.toString()) -
1206
+ parseFloat(paddingBottom.toString());
1207
+ return parseFloat(backHeight.toString());
1208
+ }
1209
+ return 0;
1210
+ } else {
1211
+ /* 未显示 */
1212
+ element = element as HTMLElement;
1213
+ const { recovery } = DOMUtilsCommonUtils.showElement(element);
1214
+ const height = DOMUtilsContext.height(element, true);
1215
+ recovery();
1216
+ return height;
1217
+ }
1218
+ }
1219
+ /**
1220
+ * 获取元素的外部宽度(包括边框和外边距)
1221
+ * @param element 要获取外部宽度的元素
1222
+ * @param [isShow=false] 是否已进行isShow,避免爆堆栈
1223
+ * @returns 元素的外部宽度,单位为像素
1224
+ * @example
1225
+ * // 获取元素a.xx的外部宽度
1226
+ * DOMUtils.outerWidth(document.querySelector("a.xx"))
1227
+ * DOMUtils.outerWidth("a.xx")
1228
+ * > 100
1229
+ * // 获取window的外部宽度
1230
+ * DOMUtils.outerWidth(window)
1231
+ * > 400
1232
+ */
1233
+ outerWidth(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1234
+ outerWidth(element: HTMLElement | string | Window | typeof globalThis | Document, isShow: boolean = false): number {
1235
+ const DOMUtilsContext = this;
1236
+ if (DOMUtilsCommonUtils.isWin(element)) {
1237
+ return DOMUtilsContext.windowApi.window.innerWidth;
1238
+ }
1239
+ if (typeof element === "string") {
1240
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1241
+ }
1242
+ element = element as HTMLElement;
1243
+ if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element))) {
1244
+ const style = DOMUtilsContext.windowApi.globalThis.getComputedStyle(element, null);
1245
+ const marginLeft = DOMUtilsCommonUtils.getStyleValue(style, "marginLeft");
1246
+ const marginRight = DOMUtilsCommonUtils.getStyleValue(style, "marginRight");
1247
+ return element.offsetWidth + marginLeft + marginRight;
1248
+ } else {
1249
+ const { recovery } = DOMUtilsCommonUtils.showElement(element);
1250
+ const outerWidth = DOMUtilsContext.outerWidth(element, true);
1251
+ recovery();
1252
+ return outerWidth;
1253
+ }
1254
+ }
1255
+ /**
1256
+ * 获取元素的外部高度(包括边框和外边距)
1257
+ * @param {HTMLElement|string} element 要获取外部高度的元素
1258
+ * @param {boolean} [isShow=false] 是否已进行isShow,避免爆堆栈
1259
+ * @returns {number} 元素的外部高度,单位为像素
1260
+ * @example
1261
+ * // 获取元素a.xx的外部高度
1262
+ * DOMUtils.outerHeight(document.querySelector("a.xx"))
1263
+ * DOMUtils.outerHeight("a.xx")
1264
+ * > 100
1265
+ * // 获取window的外部高度
1266
+ * DOMUtils.outerHeight(window)
1267
+ * > 700
1268
+ */
1269
+ outerHeight(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1270
+ outerHeight(element: HTMLElement | string | Window | typeof globalThis | Document, isShow: boolean = false): number {
1271
+ const DOMUtilsContext = this;
1272
+ if (DOMUtilsCommonUtils.isWin(element)) {
1273
+ return DOMUtilsContext.windowApi.window.innerHeight;
1274
+ }
1275
+ if (typeof element === "string") {
1276
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1277
+ }
1278
+ element = element as HTMLElement;
1279
+ if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element))) {
1280
+ const style = DOMUtilsContext.windowApi.globalThis.getComputedStyle(element, null);
1281
+ const marginTop = DOMUtilsCommonUtils.getStyleValue(style, "marginTop");
1282
+ const marginBottom = DOMUtilsCommonUtils.getStyleValue(style, "marginBottom");
1283
+ return element.offsetHeight + marginTop + marginBottom;
1284
+ } else {
1285
+ const { recovery } = DOMUtilsCommonUtils.showElement(element);
1286
+ const outerHeight = DOMUtilsContext.outerHeight(element, true);
1287
+ recovery();
1288
+ return outerHeight;
1289
+ }
1290
+ }
1291
+ /**
1292
+ * 在一定时间内改变元素的样式属性,实现动画效果
1293
+ * @param element 需要进行动画的元素
1294
+ * @param styles 动画结束时元素的样式属性
1295
+ * @param duration 动画持续时间,单位为毫秒
1296
+ * @param callback 动画结束后执行的函数
1297
+ * @example
1298
+ * // 监听元素a.xx的从显示变为隐藏
1299
+ * DOMUtils.animate(document.querySelector("a.xx"),{ top:100},1000,function(){
1300
+ * console.log("已往上位移100px")
1301
+ * })
1302
+ */
1303
+ animate(
1304
+ element: DOMUtilsTargetElementType,
1305
+ styles: CSSStyleDeclaration,
1306
+ duration: number = 1000,
1307
+ callback: (() => void) | undefined | null = null
1308
+ ) {
1309
+ const DOMUtilsContext = this;
1310
+ if (typeof element === "string") {
1311
+ element = DOMUtilsContext.selectorAll(element);
1312
+ }
1313
+ if (element == null) {
1314
+ return;
1315
+ }
1316
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1317
+ // 设置
1318
+ element.forEach(($ele) => {
1319
+ DOMUtilsContext.animate($ele as HTMLElement, styles, duration, callback);
1320
+ });
1321
+ return;
1322
+ }
1323
+ if (typeof duration !== "number" || duration <= 0) {
1324
+ throw new TypeError("duration must be a positive number");
1325
+ }
1326
+ if (typeof callback !== "function" && callback !== void 0) {
1327
+ throw new TypeError("callback must be a function or null");
1328
+ }
1329
+ if (typeof styles !== "object" || styles === void 0) {
1330
+ throw new TypeError("styles must be an object");
1331
+ }
1332
+ if (Object.keys(styles).length === 0) {
1333
+ throw new Error("styles must contain at least one property");
1334
+ }
1335
+ const start = performance.now();
1336
+ const from: {
1337
+ [prop: string]: any;
1338
+ } = {};
1339
+ const to: {
1340
+ [prop: string]: any;
1341
+ } = {};
1342
+ for (const prop in styles) {
1343
+ from[prop] = element.style[prop] || DOMUtilsContext.windowApi.globalThis.getComputedStyle(element)[prop];
1344
+ to[prop] = styles[prop];
1345
+ }
1346
+ const timer = DOMUtilsCommonUtils.setInterval(function () {
1347
+ const timePassed = performance.now() - start;
1348
+ let progress = timePassed / duration;
1349
+ if (progress > 1) {
1350
+ progress = 1;
1351
+ }
1352
+ for (const prop in styles) {
1353
+ element.style[prop] = from[prop] + (to[prop] - from[prop]) * progress + "px";
1354
+ }
1355
+ if (progress === 1) {
1356
+ DOMUtilsCommonUtils.clearInterval(timer);
1357
+ if (callback) {
1358
+ callback();
1359
+ }
1360
+ }
1361
+ }, 10);
1362
+ }
1363
+ /**
1364
+ * 将一个元素包裹在指定的HTML元素中
1365
+ * @param element 要包裹的元素
1366
+ * @param wrapperHTML 要包裹的HTML元素的字符串表示形式
1367
+ * @example
1368
+ * // 将a.xx元素外面包裹一层div
1369
+ * DOMUtils.wrap(document.querySelector("a.xx"),"<div></div>")
1370
+ */
1371
+ wrap(element: DOMUtilsTargetElementType, wrapperHTML: string) {
1372
+ const DOMUtilsContext = this;
1373
+ if (typeof element === "string") {
1374
+ element = DOMUtilsContext.selectorAll(element);
1375
+ }
1376
+ if (element == null) {
1377
+ return;
1378
+ }
1379
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1380
+ // 设置
1381
+ element.forEach(($ele) => {
1382
+ DOMUtilsContext.wrap($ele as HTMLElement, wrapperHTML);
1383
+ });
1384
+ return;
1385
+ }
1386
+ element = element as HTMLElement;
1387
+ // 创建一个新的div元素,并将wrapperHTML作为其innerHTML
1388
+ const wrapper = DOMUtilsContext.windowApi.document.createElement("div");
1389
+ DOMUtilsContext.html(wrapper, wrapperHTML);
1181
1390
 
1182
- /* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetHeight来进行计算 */
1183
- if (element.offsetHeight > 0) {
1184
- let borderTopWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderTopWidth");
1185
- let borderBottomWidth = DOMUtilsCommonUtils.getStyleValue(element, "borderBottomWidth");
1186
- let paddingTop = DOMUtilsCommonUtils.getStyleValue(element, "paddingTop");
1187
- let paddingBottom = DOMUtilsCommonUtils.getStyleValue(element, "paddingBottom");
1188
- let backHeight =
1189
- parseFloat(element.offsetHeight.toString()) -
1190
- parseFloat(borderTopWidth.toString()) -
1191
- parseFloat(borderBottomWidth.toString()) -
1192
- parseFloat(paddingTop.toString()) -
1193
- parseFloat(paddingBottom.toString());
1194
- return parseFloat(backHeight.toString());
1195
- }
1196
- return 0;
1197
- } else {
1198
- /* 未显示 */
1199
- element = element as HTMLElement;
1200
- let { recovery } = DOMUtilsCommonUtils.showElement(element);
1201
- let height = DOMUtilsContext.height(element, true);
1202
- recovery();
1203
- return height;
1204
- }
1205
- }
1206
- /**
1207
- * 获取元素的外部宽度(包括边框和外边距)
1208
- * @param element 要获取外部宽度的元素
1209
- * @param [isShow=false] 是否已进行isShow,避免爆堆栈
1210
- * @returns 元素的外部宽度,单位为像素
1211
- * @example
1212
- * // 获取元素a.xx的外部宽度
1213
- * DOMUtils.outerWidth(document.querySelector("a.xx"))
1214
- * DOMUtils.outerWidth("a.xx")
1215
- * > 100
1216
- * // 获取window的外部宽度
1217
- * DOMUtils.outerWidth(window)
1218
- * > 400
1219
- */
1220
- outerWidth(element: HTMLElement | string | Window | typeof globalThis | Document, isShow?: boolean): number;
1221
- outerWidth(
1222
- element: HTMLElement | string | Window | typeof globalThis | Document,
1223
- isShow: boolean = false
1224
- ): number {
1225
- let DOMUtilsContext = this;
1226
- if (DOMUtilsCommonUtils.isWin(element)) {
1227
- return DOMUtilsContext.windowApi.window.innerWidth;
1228
- }
1229
- if (typeof element === "string") {
1230
- element = DOMUtilsContext.selector(element) as HTMLElement;
1231
- }
1232
- if (element == null) {
1233
- // @ts-ignore
1234
- return;
1235
- }
1236
- element = element as HTMLElement;
1237
- if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element))) {
1238
- let style = DOMUtilsContext.windowApi.globalThis.getComputedStyle(element, null);
1239
- let marginLeft = DOMUtilsCommonUtils.getStyleValue(style, "marginLeft");
1240
- let marginRight = DOMUtilsCommonUtils.getStyleValue(style, "marginRight");
1241
- return element.offsetWidth + marginLeft + marginRight;
1242
- } else {
1243
- let { recovery } = DOMUtilsCommonUtils.showElement(element);
1244
- let outerWidth = DOMUtilsContext.outerWidth(element, true);
1245
- recovery();
1246
- return outerWidth;
1247
- }
1248
- }
1249
- /**
1250
- * 获取元素的外部高度(包括边框和外边距)
1251
- * @param {HTMLElement|string} element 要获取外部高度的元素
1252
- * @param {boolean} [isShow=false] 是否已进行isShow,避免爆堆栈
1253
- * @returns {number} 元素的外部高度,单位为像素
1254
- * @example
1255
- * // 获取元素a.xx的外部高度
1256
- * DOMUtils.outerHeight(document.querySelector("a.xx"))
1257
- * DOMUtils.outerHeight("a.xx")
1258
- * > 100
1259
- * // 获取window的外部高度
1260
- * DOMUtils.outerHeight(window)
1261
- * > 700
1262
- */
1263
- outerHeight(
1264
- element: HTMLElement | string | Window | typeof globalThis | Document,
1265
- isShow?: boolean
1266
- ): number;
1267
- outerHeight(
1268
- element: HTMLElement | string | Window | typeof globalThis | Document,
1269
- isShow: boolean = false
1270
- ): number {
1271
- let DOMUtilsContext = this;
1272
- if (DOMUtilsCommonUtils.isWin(element)) {
1273
- return DOMUtilsContext.windowApi.window.innerHeight;
1274
- }
1275
- if (typeof element === "string") {
1276
- element = DOMUtilsContext.selector(element) as HTMLElement;
1277
- }
1278
- if (element == null) {
1279
- // @ts-ignore
1280
- return;
1281
- }
1282
- element = element as HTMLElement;
1283
- if (isShow || (!isShow && DOMUtilsCommonUtils.isShow(element))) {
1284
- let style = DOMUtilsContext.windowApi.globalThis.getComputedStyle(element, null);
1285
- let marginTop = DOMUtilsCommonUtils.getStyleValue(style, "marginTop");
1286
- let marginBottom = DOMUtilsCommonUtils.getStyleValue(style, "marginBottom");
1287
- return element.offsetHeight + marginTop + marginBottom;
1288
- } else {
1289
- let { recovery } = DOMUtilsCommonUtils.showElement(element);
1290
- let outerHeight = DOMUtilsContext.outerHeight(element, true);
1291
- recovery();
1292
- return outerHeight;
1293
- }
1294
- }
1295
- /**
1296
- * 在一定时间内改变元素的样式属性,实现动画效果
1297
- * @param element 需要进行动画的元素
1298
- * @param styles 动画结束时元素的样式属性
1299
- * @param duration 动画持续时间,单位为毫秒
1300
- * @param callback 动画结束后执行的函数
1301
- * @example
1302
- * // 监听元素a.xx的从显示变为隐藏
1303
- * DOMUtils.animate(document.querySelector("a.xx"),{ top:100},1000,function(){
1304
- * console.log("已往上位移100px")
1305
- * })
1306
- */
1307
- animate(
1308
- element: DOMUtilsTargetElementType,
1309
- styles: CSSStyleDeclaration,
1310
- duration: number = 1000,
1311
- callback: (() => void) | undefined | null = null
1312
- ) {
1313
- let DOMUtilsContext = this;
1314
- if (typeof element === "string") {
1315
- element = DOMUtilsContext.selectorAll(element);
1316
- }
1317
- if (element == null) {
1318
- return;
1319
- }
1320
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1321
- // 设置
1322
- element.forEach(($ele) => {
1323
- DOMUtilsContext.animate($ele as HTMLElement, styles, duration, callback);
1324
- });
1325
- return;
1326
- }
1327
- if (typeof duration !== "number" || duration <= 0) {
1328
- throw new TypeError("duration must be a positive number");
1329
- }
1330
- if (typeof callback !== "function" && callback !== void 0) {
1331
- throw new TypeError("callback must be a function or null");
1332
- }
1333
- if (typeof styles !== "object" || styles === void 0) {
1334
- throw new TypeError("styles must be an object");
1335
- }
1336
- if (Object.keys(styles).length === 0) {
1337
- throw new Error("styles must contain at least one property");
1338
- }
1339
- let start = performance.now();
1340
- let from: {
1341
- [prop: string]: any;
1342
- } = {};
1343
- let to: {
1344
- [prop: string]: any;
1345
- } = {};
1346
- for (let prop in styles) {
1347
- from[prop] =
1348
- element.style[prop] || DOMUtilsContext.windowApi.globalThis.getComputedStyle(element)[prop];
1349
- to[prop] = styles[prop];
1350
- }
1351
- let timer = DOMUtilsCommonUtils.setInterval(function () {
1352
- let timePassed = performance.now() - start;
1353
- let progress = timePassed / duration;
1354
- if (progress > 1) {
1355
- progress = 1;
1356
- }
1357
- for (let prop in styles) {
1358
- element.style[prop] = from[prop] + (to[prop] - from[prop]) * progress + "px";
1359
- }
1360
- if (progress === 1) {
1361
- DOMUtilsCommonUtils.clearInterval(timer);
1362
- if (callback) {
1363
- callback();
1364
- }
1365
- }
1366
- }, 10);
1367
- }
1368
- /**
1369
- * 将一个元素包裹在指定的HTML元素中
1370
- * @param element 要包裹的元素
1371
- * @param wrapperHTML 要包裹的HTML元素的字符串表示形式
1372
- * @example
1373
- * // 将a.xx元素外面包裹一层div
1374
- * DOMUtils.wrap(document.querySelector("a.xx"),"<div></div>")
1375
- */
1376
- wrap(element: DOMUtilsTargetElementType, wrapperHTML: string) {
1377
- let DOMUtilsContext = this;
1378
- if (typeof element === "string") {
1379
- element = DOMUtilsContext.selectorAll(element);
1380
- }
1381
- if (element == null) {
1382
- return;
1383
- }
1384
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1385
- // 设置
1386
- element.forEach(($ele) => {
1387
- DOMUtilsContext.wrap($ele as HTMLElement, wrapperHTML);
1388
- });
1389
- return;
1390
- }
1391
- element = element as HTMLElement;
1392
- // 创建一个新的div元素,并将wrapperHTML作为其innerHTML
1393
- let wrapper = DOMUtilsContext.windowApi.document.createElement("div");
1394
- DOMUtilsContext.html(wrapper, wrapperHTML);
1391
+ const wrapperFirstChild = wrapper.firstChild as HTMLElement;
1392
+ // 将要包裹的元素插入目标元素前面
1393
+ const parentElement = element.parentElement as HTMLElement;
1394
+ parentElement.insertBefore(wrapperFirstChild, element);
1395
1395
 
1396
- let wrapperFirstChild = wrapper.firstChild as HTMLElement;
1397
- // 将要包裹的元素插入目标元素前面
1398
- let parentElement = element.parentElement as HTMLElement;
1399
- parentElement.insertBefore(wrapperFirstChild, element);
1396
+ // 将要包裹的元素移动到wrapper
1397
+ wrapperFirstChild.appendChild(element);
1398
+ }
1399
+ /**
1400
+ * 获取当前元素的前一个兄弟元素
1401
+ * @param element 当前元素
1402
+ * @returns 前一个兄弟元素
1403
+ * @example
1404
+ * // 获取a.xx元素前一个兄弟元素
1405
+ * DOMUtils.prev(document.querySelector("a.xx"))
1406
+ * DOMUtils.prev("a.xx")
1407
+ * > <div ...>....</div>
1408
+ */
1409
+ prev(element: HTMLElement | string): HTMLElement;
1410
+ prev(element: HTMLElement | string) {
1411
+ const DOMUtilsContext = this;
1412
+ if (typeof element === "string") {
1413
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1414
+ }
1415
+ if (element == null) {
1416
+ return;
1417
+ }
1418
+ return element.previousElementSibling as HTMLElement;
1419
+ }
1400
1420
 
1401
- // 将要包裹的元素移动到wrapper中
1402
- wrapperFirstChild.appendChild(element);
1403
- }
1404
- /**
1405
- * 获取当前元素的前一个兄弟元素
1406
- * @param element 当前元素
1407
- * @returns 前一个兄弟元素
1408
- * @example
1409
- * // 获取a.xx元素前一个兄弟元素
1410
- * DOMUtils.prev(document.querySelector("a.xx"))
1411
- * DOMUtils.prev("a.xx")
1412
- * > <div ...>....</div>
1413
- */
1414
- prev(element: HTMLElement | string): HTMLElement;
1415
- prev(element: HTMLElement | string) {
1416
- let DOMUtilsContext = this;
1417
- if (typeof element === "string") {
1418
- element = DOMUtilsContext.selector(element) as HTMLElement;
1419
- }
1420
- if (element == null) {
1421
- return;
1422
- }
1423
- return element.previousElementSibling as HTMLElement;
1424
- }
1421
+ /**
1422
+ * 获取当前元素的后一个兄弟元素
1423
+ * @param element 当前元素
1424
+ * @returns 后一个兄弟元素
1425
+ * @example
1426
+ * // 获取a.xx元素前一个兄弟元素
1427
+ * DOMUtils.next(document.querySelector("a.xx"))
1428
+ * DOMUtils.next("a.xx")
1429
+ * > <div ...>....</div>
1430
+ */
1431
+ next(element: HTMLElement | string): HTMLElement;
1432
+ next(element: HTMLElement | string) {
1433
+ const DOMUtilsContext = this;
1434
+ if (typeof element === "string") {
1435
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1436
+ }
1437
+ if (element == null) {
1438
+ return;
1439
+ }
1440
+ return element.nextElementSibling as HTMLElement;
1441
+ }
1442
+ /**
1443
+ * 取消挂载在window下的DOMUtils并返回DOMUtils
1444
+ * @example
1445
+ * let DOMUtils = window.DOMUtils.noConflict()
1446
+ */
1447
+ noConflict() {
1448
+ const DOMUtilsContext = this;
1449
+ if ((DOMUtilsContext.windowApi.window as any).DOMUtils) {
1450
+ DOMUtilsCommonUtils.delete(window, "DOMUtils");
1451
+ }
1452
+ (DOMUtilsContext.windowApi.window as any).DOMUtils = this;
1453
+ return this;
1454
+ }
1455
+ /**
1456
+ * 获取当前元素的所有兄弟元素
1457
+ * @param element 当前元素
1458
+ * @returns 所有兄弟元素
1459
+ * @example
1460
+ * // 获取a.xx元素所有兄弟元素
1461
+ * DOMUtils.siblings(document.querySelector("a.xx"))
1462
+ * DOMUtils.siblings("a.xx")
1463
+ * > (3)[div.logo-wrapper, div.forum-block, div.more-btn-desc]
1464
+ */
1465
+ siblings(element: HTMLElement | string): HTMLElement[];
1466
+ siblings(element: HTMLElement | string) {
1467
+ const DOMUtilsContext = this;
1468
+ if (typeof element === "string") {
1469
+ element = DOMUtilsContext.selector(element) as HTMLElement;
1470
+ }
1471
+ if (element == null) {
1472
+ return;
1473
+ }
1474
+ return Array.from((element.parentElement as HTMLElement).children as HTMLCollectionOf<HTMLElement>).filter(
1475
+ (child) => child !== element
1476
+ );
1477
+ }
1478
+ /**
1479
+ * 获取当前元素的父元素
1480
+ * @param element 当前元素
1481
+ * @returns 父元素
1482
+ * @example
1483
+ * // 获取a.xx元素的父元素
1484
+ * DOMUtils.parent(document.querySelector("a.xx"))
1485
+ * DOMUtils.parent("a.xx")
1486
+ * > <div ...>....</div>
1487
+ */
1488
+ parent(element: HTMLElement | string): HTMLElement;
1489
+ /**
1490
+ * 获取当前元素的父元素
1491
+ * @param element 当前元素
1492
+ * @returns 父元素
1493
+ * @example
1494
+ * // 获取a.xx元素的父元素
1495
+ * DOMUtils.parent(document.querySelector("a.xx"))
1496
+ * DOMUtils.parent("a.xx")
1497
+ * > <div ...>....</div>
1498
+ */
1499
+ parent(element: HTMLElement[] | NodeList): HTMLElement[];
1500
+ /**
1501
+ * 获取当前元素的父元素
1502
+ * @param element 当前元素
1503
+ * @returns 父元素
1504
+ * @example
1505
+ * // 获取a.xx元素的父元素
1506
+ * DOMUtils.parent(document.querySelector("a.xx"))
1507
+ * DOMUtils.parent("a.xx")
1508
+ * > <div ...>....</div>
1509
+ */
1510
+ parent(element: HTMLElement | Element | Node | NodeList | string | HTMLElement[]) {
1511
+ const DOMUtilsContext = this;
1512
+ if (typeof element === "string") {
1513
+ element = DOMUtilsContext.selector<HTMLElement>(element)!;
1514
+ }
1515
+ if (element == null) {
1516
+ return;
1517
+ }
1518
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1519
+ const resultArray: HTMLElement[] = [];
1520
+ element.forEach(($ele) => {
1521
+ resultArray.push(DOMUtilsContext.parent($ele as HTMLElement));
1522
+ });
1523
+ return resultArray;
1524
+ } else {
1525
+ return element.parentElement;
1526
+ }
1527
+ }
1528
+ /**
1529
+ * 将字符串转为Element元素
1530
+ * @param html
1531
+ * @param useParser 是否使用DOMParser来生成元素,有些时候通过DOMParser生成的元素有点问题
1532
+ * + true 使用DOMPraser来转换字符串
1533
+ * + false (默认)创建一个div,里面放入字符串,然后提取firstChild
1534
+ * @param isComplete 是否是完整的
1535
+ * + true 如果useParser为true,那么返回整个使用DOMParser转换成的Document
1536
+ * 如果useParser为false,返回一个DIV元素,DIV元素内包裹着需要转换的字符串
1537
+ * + false (默认)如果useParser为true,那么返回整个使用DOMParser转换成的Document的body
1538
+ * 如果useParser为false,返回一个DIV元素的firstChild
1539
+ * @example
1540
+ * // 将字符串转为Element元素
1541
+ * DOMUtils.parseHTML("<a href='xxxx'></a>")
1542
+ * > <a href="xxxx"></a>
1543
+ * @example
1544
+ * // 使用DOMParser将字符串转为Element元素
1545
+ * DOMUtils.parseHTML("<a href='xxxx'></a>",true)
1546
+ * > <a href="xxxx"></a>
1547
+ * @example
1548
+ * // 由于需要转换的元素是多个元素,将字符串转为完整的Element元素
1549
+ * DOMUtils.parseHTML("<a href='xxxx'></a><a href='xxxx'></a>",false, true)
1550
+ * > <div><a href="xxxx"></a><a href='xxxx'></a></div>
1551
+ * @example
1552
+ * // 由于需要转换的元素是多个元素,使用DOMParser将字符串转为完整的Element元素
1553
+ * DOMUtils.parseHTML("<a href='xxxx'></a><a href='xxxx'></a>",true, true)
1554
+ * > #document
1555
+ */
1556
+ parseHTML<T1 extends boolean, T2 extends boolean>(
1557
+ html: string,
1558
+ useParser?: T1,
1559
+ isComplete?: T2
1560
+ ): ParseHTMLReturnType<T1, T2>;
1561
+ parseHTML(html: string, useParser = false, isComplete = false) {
1562
+ const DOMUtilsContext = this;
1563
+ // 去除html前后的空格
1564
+ html = html.trim();
1565
+ function parseHTMLByDOMParser() {
1566
+ const parser = new DOMParser();
1567
+ if (isComplete) {
1568
+ return parser.parseFromString(html, "text/html");
1569
+ } else {
1570
+ return parser.parseFromString(html, "text/html").body.firstChild;
1571
+ }
1572
+ }
1573
+ function parseHTMLByCreateDom() {
1574
+ const tempDIV = DOMUtilsContext.windowApi.document.createElement("div");
1575
+ DOMUtilsContext.html(tempDIV, html);
1576
+ if (isComplete) {
1577
+ return tempDIV;
1578
+ } else {
1579
+ return tempDIV.firstChild;
1580
+ }
1581
+ }
1582
+ if (useParser) {
1583
+ return parseHTMLByDOMParser();
1584
+ } else {
1585
+ return parseHTMLByCreateDom();
1586
+ }
1587
+ }
1588
+ /**
1589
+ * 序列化表单元素
1590
+ * @param $form 表单元素
1591
+ * @example
1592
+ * DOMUtils.serialize(document.querySelector("form"))
1593
+ * > xxx=xxx&aaa=
1594
+ */
1595
+ serialize($form: HTMLFormElement): string {
1596
+ const elements = $form.elements;
1597
+ const serializedArray: { name: string; value: string }[] = [];
1425
1598
 
1426
- /**
1427
- * 获取当前元素的后一个兄弟元素
1428
- * @param element 当前元素
1429
- * @returns 后一个兄弟元素
1430
- * @example
1431
- * // 获取a.xx元素前一个兄弟元素
1432
- * DOMUtils.next(document.querySelector("a.xx"))
1433
- * DOMUtils.next("a.xx")
1434
- * > <div ...>....</div>
1435
- */
1436
- next(element: HTMLElement | string): HTMLElement;
1437
- next(element: HTMLElement | string) {
1438
- let DOMUtilsContext = this;
1439
- if (typeof element === "string") {
1440
- element = DOMUtilsContext.selector(element) as HTMLElement;
1441
- }
1442
- if (element == null) {
1443
- return;
1444
- }
1445
- return element.nextElementSibling as HTMLElement;
1446
- }
1447
- /**
1448
- * 取消挂载在window下的DOMUtils并返回DOMUtils
1449
- * @example
1450
- * let DOMUtils = window.DOMUtils.noConflict()
1451
- */
1452
- noConflict() {
1453
- let DOMUtilsContext = this;
1454
- if ((DOMUtilsContext.windowApi.window as any).DOMUtils) {
1455
- DOMUtilsCommonUtils.delete(window, "DOMUtils");
1456
- }
1457
- (DOMUtilsContext.windowApi.window as any).DOMUtils = this;
1458
- return this;
1459
- }
1460
- /**
1461
- * 获取当前元素的所有兄弟元素
1462
- * @param element 当前元素
1463
- * @returns 所有兄弟元素
1464
- * @example
1465
- * // 获取a.xx元素所有兄弟元素
1466
- * DOMUtils.siblings(document.querySelector("a.xx"))
1467
- * DOMUtils.siblings("a.xx")
1468
- * > (3) [div.logo-wrapper, div.forum-block, div.more-btn-desc]
1469
- */
1470
- siblings(element: HTMLElement | string): HTMLElement[];
1471
- siblings(element: HTMLElement | string) {
1472
- let DOMUtilsContext = this;
1473
- if (typeof element === "string") {
1474
- element = DOMUtilsContext.selector(element) as HTMLElement;
1475
- }
1476
- if (element == null) {
1477
- return;
1478
- }
1479
- return Array.from(
1480
- (element.parentElement as HTMLElement).children as HTMLCollectionOf<HTMLElement>
1481
- ).filter((child) => child !== element);
1482
- }
1483
- /**
1484
- * 获取当前元素的父元素
1485
- * @param element 当前元素
1486
- * @returns 父元素
1487
- * @example
1488
- * // 获取a.xx元素的父元素
1489
- * DOMUtils.parent(document.querySelector("a.xx"))
1490
- * DOMUtils.parent("a.xx")
1491
- * > <div ...>....</div>
1492
- */
1493
- parent(element: HTMLElement | string): HTMLElement;
1494
- /**
1495
- * 获取当前元素的父元素
1496
- * @param element 当前元素
1497
- * @returns 父元素
1498
- * @example
1499
- * // 获取a.xx元素的父元素
1500
- * DOMUtils.parent(document.querySelector("a.xx"))
1501
- * DOMUtils.parent("a.xx")
1502
- * > <div ...>....</div>
1503
- */
1504
- parent(element: HTMLElement[] | NodeList): HTMLElement[];
1505
- /**
1506
- * 获取当前元素的父元素
1507
- * @param element 当前元素
1508
- * @returns 父元素
1509
- * @example
1510
- * // 获取a.xx元素的父元素
1511
- * DOMUtils.parent(document.querySelector("a.xx"))
1512
- * DOMUtils.parent("a.xx")
1513
- * > <div ...>....</div>
1514
- */
1515
- parent(element: HTMLElement | Element | Node | NodeList | string | HTMLElement[]) {
1516
- let DOMUtilsContext = this;
1517
- if (typeof element === "string") {
1518
- element = DOMUtilsContext.selector<HTMLElement>(element)!;
1519
- }
1520
- if (element == null) {
1521
- return;
1522
- }
1523
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1524
- let resultArray: HTMLElement[] = [];
1525
- element.forEach(($ele) => {
1526
- resultArray.push(DOMUtilsContext.parent($ele as HTMLElement));
1527
- });
1528
- return resultArray;
1529
- } else {
1530
- return element.parentElement;
1531
- }
1532
- }
1533
- /**
1534
- * 将字符串转为Element元素
1535
- * @param html
1536
- * @param useParser 是否使用DOMParser来生成元素,有些时候通过DOMParser生成的元素有点问题
1537
- * + true 使用DOMPraser来转换字符串
1538
- * + false (默认)创建一个div,里面放入字符串,然后提取firstChild
1539
- * @param isComplete 是否是完整的
1540
- * + true 如果useParser为true,那么返回整个使用DOMParser转换成的Document
1541
- * 如果useParser为false,返回一个DIV元素,DIV元素内包裹着需要转换的字符串
1542
- * + false (默认)如果useParser为true,那么返回整个使用DOMParser转换成的Document的body
1543
- * 如果useParser为false,返回一个DIV元素的firstChild
1544
- * @example
1545
- * // 将字符串转为Element元素
1546
- * DOMUtils.parseHTML("<a href='xxxx'></a>")
1547
- * > <a href="xxxx"></a>
1548
- * @example
1549
- * // 使用DOMParser将字符串转为Element元素
1550
- * DOMUtils.parseHTML("<a href='xxxx'></a>",true)
1551
- * > <a href="xxxx"></a>
1552
- * @example
1553
- * // 由于需要转换的元素是多个元素,将字符串转为完整的Element元素
1554
- * DOMUtils.parseHTML("<a href='xxxx'></a><a href='xxxx'></a>",false, true)
1555
- * > <div><a href="xxxx"></a><a href='xxxx'></a></div>
1556
- * @example
1557
- * // 由于需要转换的元素是多个元素,使用DOMParser将字符串转为完整的Element元素
1558
- * DOMUtils.parseHTML("<a href='xxxx'></a><a href='xxxx'></a>",true, true)
1559
- * > #document
1560
- */
1561
- parseHTML<T1 extends boolean, T2 extends boolean>(
1562
- html: string,
1563
- useParser?: T1,
1564
- isComplete?: T2
1565
- ): ParseHTMLReturnType<T1, T2>;
1566
- parseHTML(html: string, useParser = false, isComplete = false) {
1567
- let DOMUtilsContext = this;
1568
- // 去除html前后的空格
1569
- html = html.trim();
1570
- function parseHTMLByDOMParser() {
1571
- let parser = new DOMParser();
1572
- if (isComplete) {
1573
- return parser.parseFromString(html, "text/html");
1574
- } else {
1575
- return parser.parseFromString(html, "text/html").body.firstChild;
1576
- }
1577
- }
1578
- function parseHTMLByCreateDom() {
1579
- let tempDIV = DOMUtilsContext.windowApi.document.createElement("div");
1580
- DOMUtilsContext.html(tempDIV, html);
1581
- if (isComplete) {
1582
- return tempDIV;
1583
- } else {
1584
- return tempDIV.firstChild;
1585
- }
1586
- }
1587
- if (useParser) {
1588
- return parseHTMLByDOMParser();
1589
- } else {
1590
- return parseHTMLByCreateDom();
1591
- }
1592
- }
1593
- /**
1594
- * 序列化表单元素
1595
- * @param $form 表单元素
1596
- * @example
1597
- * DOMUtils.serialize(document.querySelector("form"))
1598
- * > xxx=xxx&aaa=
1599
- */
1600
- serialize($form: HTMLFormElement): string {
1601
- const elements = $form.elements;
1602
- let serializedArray: { name: string; value: string }[] = [];
1599
+ for (let i = 0; i < elements.length; i++) {
1600
+ const element = elements[i] as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
1603
1601
 
1604
- for (let i = 0; i < elements.length; i++) {
1605
- const element = elements[i] as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
1602
+ if (
1603
+ element.name &&
1604
+ !element.disabled &&
1605
+ ((element as HTMLInputElement).checked ||
1606
+ ["text", "hidden", "password", "textarea", "select-one", "select-multiple"].includes(element.type))
1607
+ ) {
1608
+ if (element.type === "select-multiple") {
1609
+ for (let j = 0; j < (element as HTMLSelectElement).options.length; j++) {
1610
+ if ((element as HTMLSelectElement).options[j].selected) {
1611
+ serializedArray.push({
1612
+ name: (element as HTMLSelectElement).name,
1613
+ value: (element as HTMLSelectElement).options[j].value,
1614
+ });
1615
+ }
1616
+ }
1617
+ } else {
1618
+ serializedArray.push({ name: element.name, value: element.value });
1619
+ }
1620
+ }
1621
+ }
1606
1622
 
1607
- if (
1608
- element.name &&
1609
- !element.disabled &&
1610
- ((element as HTMLInputElement).checked ||
1611
- ["text", "hidden", "password", "textarea", "select-one", "select-multiple"].includes(element.type))
1612
- ) {
1613
- if (element.type === "select-multiple") {
1614
- for (let j = 0; j < (element as HTMLSelectElement).options.length; j++) {
1615
- if ((element as HTMLSelectElement).options[j].selected) {
1616
- serializedArray.push({
1617
- name: (element as HTMLSelectElement).name,
1618
- value: (element as HTMLSelectElement).options[j].value,
1619
- });
1620
- }
1621
- }
1622
- } else {
1623
- serializedArray.push({ name: element.name, value: element.value });
1624
- }
1625
- }
1626
- }
1623
+ return serializedArray
1624
+ .map((item) => `${encodeURIComponent(item.name)}=${encodeURIComponent(item.value)}`)
1625
+ .join("&");
1626
+ }
1627
+ /**
1628
+ * 显示元素
1629
+ * @param target 当前元素
1630
+ * @param checkVisiblie 是否检测元素是否显示
1631
+ * + true (默认)如果检测到还未显示,则强制使用display: unset !important;
1632
+ * + false 不检测,直接设置display属性为空
1633
+ * @example
1634
+ * // 显示a.xx元素
1635
+ * DOMUtils.show(document.querySelector("a.xx"))
1636
+ * DOMUtils.show(document.querySelectorAll("a.xx"))
1637
+ * DOMUtils.show("a.xx")
1638
+ */
1639
+ show(target: DOMUtilsTargetElementType, checkVisiblie: boolean = true) {
1640
+ const DOMUtilsContext = this;
1641
+ if (target == null) {
1642
+ return;
1643
+ }
1644
+ if (typeof target === "string") {
1645
+ target = DOMUtilsContext.selectorAll(target);
1646
+ }
1647
+ if (target instanceof NodeList || target instanceof Array) {
1648
+ target = target as HTMLElement[];
1649
+ for (const element of target) {
1650
+ DOMUtilsContext.show(element, checkVisiblie);
1651
+ }
1652
+ } else {
1653
+ target = target as HTMLElement;
1654
+ target.style.display = "";
1655
+ if (checkVisiblie) {
1656
+ if (!DOMUtilsCommonUtils.isShow(target)) {
1657
+ /* 仍然是不显示,尝试使用强覆盖 */
1658
+ target.style.setProperty("display", "unset", "important");
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+ /**
1664
+ * 隐藏元素
1665
+ * @param target 当前元素
1666
+ * @param checkVisiblie 是否检测元素是否显示
1667
+ * + true (默认)如果检测到显示,则强制使用display: none !important;
1668
+ * + false 不检测,直接设置display属性为none
1669
+ * @example
1670
+ * // 隐藏a.xx元素
1671
+ * DOMUtils.hide(document.querySelector("a.xx"))
1672
+ * DOMUtils.hide(document.querySelectorAll("a.xx"))
1673
+ * DOMUtils.hide("a.xx")
1674
+ */
1675
+ hide(target: DOMUtilsTargetElementType, checkVisiblie: boolean = true) {
1676
+ const DOMUtilsContext = this;
1677
+ if (target == null) {
1678
+ return;
1679
+ }
1680
+ if (typeof target === "string") {
1681
+ target = DOMUtilsContext.selectorAll(target);
1682
+ }
1683
+ if (target instanceof NodeList || target instanceof Array) {
1684
+ target = target as HTMLElement[];
1685
+ for (const element of target) {
1686
+ DOMUtilsContext.hide(element, checkVisiblie);
1687
+ }
1688
+ } else {
1689
+ target = target as HTMLElement;
1690
+ target.style.display = "none";
1691
+ if (checkVisiblie) {
1692
+ if (DOMUtilsCommonUtils.isShow(target)) {
1693
+ /* 仍然是显示,尝试使用强覆盖 */
1694
+ target.style.setProperty("display", "none", "important");
1695
+ }
1696
+ }
1697
+ }
1698
+ }
1699
+ /**
1700
+ * 淡入元素
1701
+ * @param element 当前元素
1702
+ * @param duration 动画持续时间(毫秒),默认400毫秒
1703
+ * @param callback 动画结束的回调
1704
+ * @example
1705
+ * // 元素a.xx淡入
1706
+ * DOMUtils.fadeIn(document.querySelector("a.xx"),2500,()=>{
1707
+ * console.log("淡入完毕");
1708
+ * })
1709
+ * DOMUtils.fadeIn("a.xx",undefined,()=>{
1710
+ * console.log("淡入完毕");
1711
+ * })
1712
+ */
1713
+ fadeIn(element: DOMUtilsTargetElementType, duration: number = 400, callback?: () => void) {
1714
+ if (element == null) {
1715
+ return;
1716
+ }
1717
+ const DOMUtilsContext = this;
1718
+ if (typeof element === "string") {
1719
+ element = DOMUtilsContext.selectorAll(element);
1720
+ }
1721
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1722
+ // 设置
1723
+ element.forEach(($ele) => {
1724
+ DOMUtilsContext.fadeIn($ele as HTMLElement, duration, callback);
1725
+ });
1726
+ return;
1727
+ }
1728
+ element.style.opacity = "0";
1729
+ element.style.display = "";
1730
+ let start: number = null as any;
1731
+ let timer: number = null as any;
1732
+ function step(timestamp: number) {
1733
+ if (!start) start = timestamp;
1734
+ const progress = timestamp - start;
1735
+ element = element as HTMLElement;
1736
+ element.style.opacity = Math.min(progress / duration, 1).toString();
1737
+ if (progress < duration) {
1738
+ DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1739
+ } else {
1740
+ if (callback && typeof callback === "function") {
1741
+ callback();
1742
+ }
1743
+ DOMUtilsContext.windowApi.window.cancelAnimationFrame(timer);
1744
+ }
1745
+ }
1746
+ timer = DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1747
+ }
1748
+ /**
1749
+ * 淡出元素
1750
+ * @param element 当前元素
1751
+ * @param duration 动画持续时间(毫秒),默认400毫秒
1752
+ * @param callback 动画结束的回调
1753
+ * @example
1754
+ * // 元素a.xx淡出
1755
+ * DOMUtils.fadeOut(document.querySelector("a.xx"),2500,()=>{
1756
+ * console.log("淡出完毕");
1757
+ * })
1758
+ * DOMUtils.fadeOut("a.xx",undefined,()=>{
1759
+ * console.log("淡出完毕");
1760
+ * })
1761
+ */
1762
+ fadeOut(element: DOMUtilsTargetElementType, duration: number = 400, callback?: () => void) {
1763
+ const DOMUtilsContext = this;
1764
+ if (element == null) {
1765
+ return;
1766
+ }
1767
+ if (typeof element === "string") {
1768
+ element = DOMUtilsContext.selectorAll(element);
1769
+ }
1770
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1771
+ // 设置
1772
+ element.forEach(($ele) => {
1773
+ DOMUtilsContext.fadeOut($ele as HTMLElement, duration, callback);
1774
+ });
1775
+ return;
1776
+ }
1777
+ element.style.opacity = "1";
1778
+ let start: number = null as any;
1779
+ let timer: number = null as any;
1780
+ function step(timestamp: number) {
1781
+ if (!start) start = timestamp;
1782
+ const progress = timestamp - start;
1783
+ element = element as HTMLElement;
1784
+ element.style.opacity = Math.max(1 - progress / duration, 0).toString();
1785
+ if (progress < duration) {
1786
+ DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1787
+ } else {
1788
+ element.style.display = "none";
1789
+ if (typeof callback === "function") {
1790
+ callback();
1791
+ }
1792
+ DOMUtilsContext.windowApi.window.cancelAnimationFrame(timer);
1793
+ }
1794
+ }
1795
+ timer = DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1796
+ }
1797
+ /**
1798
+ * 切换元素的显示和隐藏状态
1799
+ * @param element 当前元素
1800
+ * @param checkVisiblie 是否检测元素是否显示
1801
+ * @example
1802
+ * // 如果元素a.xx当前是隐藏,则显示,如果是显示,则隐藏
1803
+ * DOMUtils.toggle(document.querySelector("a.xx"))
1804
+ * DOMUtils.toggle("a.xx")
1805
+ */
1806
+ toggle(element: DOMUtilsTargetElementType, checkVisiblie?: boolean) {
1807
+ const DOMUtilsContext = this;
1808
+ if (typeof element === "string") {
1809
+ element = DOMUtilsContext.selectorAll(element);
1810
+ }
1811
+ if (element == null) {
1812
+ return;
1813
+ }
1814
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1815
+ // 设置
1816
+ element.forEach(($ele) => {
1817
+ DOMUtilsContext.toggle($ele as HTMLElement);
1818
+ });
1819
+ return;
1820
+ }
1821
+ if (DOMUtilsContext.windowApi.globalThis.getComputedStyle(element).getPropertyValue("display") === "none") {
1822
+ DOMUtilsContext.show(element, checkVisiblie);
1823
+ } else {
1824
+ DOMUtilsContext.hide(element, checkVisiblie);
1825
+ }
1826
+ }
1827
+ /**
1828
+ * 创建一个新的DOMUtils实例
1829
+ * @param option
1830
+ * @returns
1831
+ */
1832
+ createDOMUtils(option?: WindowApiOption) {
1833
+ return new DOMUtils(option);
1834
+ }
1835
+ /**
1836
+ * 获取文字的位置信息
1837
+ * @param $input 输入框
1838
+ * @param selectionStart 起始位置
1839
+ * @param selectionEnd 结束位置
1840
+ * @example
1841
+ * DOMUtils.getTextBoundingRect(document.querySelector("input"));
1842
+ */
1843
+ getTextBoundingRect(
1844
+ $input: HTMLInputElement,
1845
+ selectionStart?: number | string,
1846
+ selectionEnd?: number | string
1847
+ ): DOMRect {
1848
+ const DOMUtilsContext = this;
1849
+ // Basic parameter validation
1850
+ if (!$input || !("value" in $input)) return $input;
1851
+ if (selectionStart == null) {
1852
+ selectionStart = $input.selectionStart || 0;
1853
+ }
1854
+ if (selectionEnd == null) {
1855
+ selectionEnd = $input.selectionEnd || 0;
1856
+ }
1857
+ if (typeof selectionStart == "string") selectionStart = parseFloat(selectionStart);
1858
+ if (typeof selectionStart != "number" || isNaN(selectionStart)) {
1859
+ selectionStart = 0;
1860
+ }
1861
+ if (selectionStart < 0) selectionStart = 0;
1862
+ else selectionStart = Math.min($input.value.length, selectionStart);
1863
+ if (typeof selectionEnd == "string") selectionEnd = parseFloat(selectionEnd);
1864
+ if (typeof selectionEnd != "number" || isNaN(selectionEnd) || selectionEnd < selectionStart) {
1865
+ selectionEnd = selectionStart;
1866
+ }
1867
+ if (selectionEnd < 0) selectionEnd = 0;
1868
+ else selectionEnd = Math.min($input.value.length, selectionEnd);
1627
1869
 
1628
- return serializedArray
1629
- .map((item) => `${encodeURIComponent(item.name)}=${encodeURIComponent(item.value)}`)
1630
- .join("&");
1631
- }
1632
- /**
1633
- * 显示元素
1634
- * @param target 当前元素
1635
- * @param checkVisiblie 是否检测元素是否显示
1636
- * + true (默认)如果检测到还未显示,则强制使用display: unset !important;
1637
- * + false 不检测,直接设置display属性为空
1638
- * @example
1639
- * // 显示a.xx元素
1640
- * DOMUtils.show(document.querySelector("a.xx"))
1641
- * DOMUtils.show(document.querySelectorAll("a.xx"))
1642
- * DOMUtils.show("a.xx")
1643
- */
1644
- show(target: DOMUtilsTargetElementType, checkVisiblie: boolean = true) {
1645
- let DOMUtilsContext = this;
1646
- if (target == null) {
1647
- return;
1648
- }
1649
- if (typeof target === "string") {
1650
- target = DOMUtilsContext.selectorAll(target);
1651
- }
1652
- if (target instanceof NodeList || target instanceof Array) {
1653
- target = target as HTMLElement[];
1654
- for (const element of target) {
1655
- DOMUtilsContext.show(element, checkVisiblie);
1656
- }
1657
- } else {
1658
- target = target as HTMLElement;
1659
- target.style.display = "";
1660
- if (checkVisiblie) {
1661
- if (!DOMUtilsCommonUtils.isShow(target)) {
1662
- /* 仍然是不显示,尝试使用强覆盖 */
1663
- target.style.setProperty("display", "unset", "important");
1664
- }
1665
- }
1666
- }
1667
- }
1668
- /**
1669
- * 隐藏元素
1670
- * @param target 当前元素
1671
- * @param checkVisiblie 是否检测元素是否显示
1672
- * + true (默认)如果检测到显示,则强制使用display: none !important;
1673
- * + false 不检测,直接设置display属性为none
1674
- * @example
1675
- * // 隐藏a.xx元素
1676
- * DOMUtils.hide(document.querySelector("a.xx"))
1677
- * DOMUtils.hide(document.querySelectorAll("a.xx"))
1678
- * DOMUtils.hide("a.xx")
1679
- */
1680
- hide(target: DOMUtilsTargetElementType, checkVisiblie: boolean = true) {
1681
- let DOMUtilsContext = this;
1682
- if (target == null) {
1683
- return;
1684
- }
1685
- if (typeof target === "string") {
1686
- target = DOMUtilsContext.selectorAll(target);
1687
- }
1688
- if (target instanceof NodeList || target instanceof Array) {
1689
- target = target as HTMLElement[];
1690
- for (const element of target) {
1691
- DOMUtilsContext.hide(element, checkVisiblie);
1692
- }
1693
- } else {
1694
- target = target as HTMLElement;
1695
- target.style.display = "none";
1696
- if (checkVisiblie) {
1697
- if (DOMUtilsCommonUtils.isShow(target)) {
1698
- /* 仍然是显示,尝试使用强覆盖 */
1699
- target.style.setProperty("display", "none", "important");
1700
- }
1701
- }
1702
- }
1703
- }
1704
- /**
1705
- * 淡入元素
1706
- * @param element 当前元素
1707
- * @param duration 动画持续时间(毫秒),默认400毫秒
1708
- * @param callback 动画结束的回调
1709
- * @example
1710
- * // 元素a.xx淡入
1711
- * DOMUtils.fadeIn(document.querySelector("a.xx"),2500,()=>{
1712
- * console.log("淡入完毕");
1713
- * })
1714
- * DOMUtils.fadeIn("a.xx",undefined,()=>{
1715
- * console.log("淡入完毕");
1716
- * })
1717
- */
1718
- fadeIn(element: DOMUtilsTargetElementType, duration: number = 400, callback?: () => void) {
1719
- if (element == null) {
1720
- return;
1721
- }
1722
- let DOMUtilsContext = this;
1723
- if (typeof element === "string") {
1724
- element = DOMUtilsContext.selectorAll(element);
1725
- }
1726
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1727
- // 设置
1728
- element.forEach(($ele) => {
1729
- DOMUtilsContext.fadeIn($ele as HTMLElement, duration, callback);
1730
- });
1731
- return;
1732
- }
1733
- element.style.opacity = "0";
1734
- element.style.display = "";
1735
- let start: number = null as any;
1736
- let timer: number = null as any;
1737
- function step(timestamp: number) {
1738
- if (!start) start = timestamp;
1739
- let progress = timestamp - start;
1740
- element = element as HTMLElement;
1741
- element.style.opacity = Math.min(progress / duration, 1).toString();
1742
- if (progress < duration) {
1743
- DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1744
- } else {
1745
- if (callback && typeof callback === "function") {
1746
- callback();
1747
- }
1748
- DOMUtilsContext.windowApi.window.cancelAnimationFrame(timer);
1749
- }
1750
- }
1751
- timer = DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1752
- }
1753
- /**
1754
- * 淡出元素
1755
- * @param element 当前元素
1756
- * @param duration 动画持续时间(毫秒),默认400毫秒
1757
- * @param callback 动画结束的回调
1758
- * @example
1759
- * // 元素a.xx淡出
1760
- * DOMUtils.fadeOut(document.querySelector("a.xx"),2500,()=>{
1761
- * console.log("淡出完毕");
1762
- * })
1763
- * DOMUtils.fadeOut("a.xx",undefined,()=>{
1764
- * console.log("淡出完毕");
1765
- * })
1766
- */
1767
- fadeOut(element: DOMUtilsTargetElementType, duration: number = 400, callback?: () => void) {
1768
- let DOMUtilsContext = this;
1769
- if (element == null) {
1770
- return;
1771
- }
1772
- if (typeof element === "string") {
1773
- element = DOMUtilsContext.selectorAll(element);
1774
- }
1775
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1776
- // 设置
1777
- element.forEach(($ele) => {
1778
- DOMUtilsContext.fadeOut($ele as HTMLElement, duration, callback);
1779
- });
1780
- return;
1781
- }
1782
- element.style.opacity = "1";
1783
- let start: number = null as any;
1784
- let timer: number = null as any;
1785
- function step(timestamp: number) {
1786
- if (!start) start = timestamp;
1787
- let progress = timestamp - start;
1788
- element = element as HTMLElement;
1789
- element.style.opacity = Math.max(1 - progress / duration, 0).toString();
1790
- if (progress < duration) {
1791
- DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1792
- } else {
1793
- element.style.display = "none";
1794
- if (typeof callback === "function") {
1795
- callback();
1796
- }
1797
- DOMUtilsContext.windowApi.window.cancelAnimationFrame(timer);
1798
- }
1799
- }
1800
- timer = DOMUtilsContext.windowApi.window.requestAnimationFrame(step);
1801
- }
1802
- /**
1803
- * 切换元素的显示和隐藏状态
1804
- * @param element 当前元素
1805
- * @param checkVisiblie 是否检测元素是否显示
1806
- * @example
1807
- * // 如果元素a.xx当前是隐藏,则显示,如果是显示,则隐藏
1808
- * DOMUtils.toggle(document.querySelector("a.xx"))
1809
- * DOMUtils.toggle("a.xx")
1810
- */
1811
- toggle(element: DOMUtilsTargetElementType, checkVisiblie?: boolean) {
1812
- let DOMUtilsContext = this;
1813
- if (typeof element === "string") {
1814
- element = DOMUtilsContext.selectorAll(element);
1815
- }
1816
- if (element == null) {
1817
- return;
1818
- }
1819
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1820
- // 设置
1821
- element.forEach(($ele) => {
1822
- DOMUtilsContext.toggle($ele as HTMLElement);
1823
- });
1824
- return;
1825
- }
1826
- if (
1827
- DOMUtilsContext.windowApi.globalThis.getComputedStyle(element).getPropertyValue("display") === "none"
1828
- ) {
1829
- DOMUtilsContext.show(element, checkVisiblie);
1830
- } else {
1831
- DOMUtilsContext.hide(element, checkVisiblie);
1832
- }
1833
- }
1834
- /**
1835
- * 创建一个新的DOMUtils实例
1836
- * @param option
1837
- * @returns
1838
- */
1839
- createDOMUtils(option?: WindowApiOption) {
1840
- return new DOMUtils(option);
1841
- }
1842
- /**
1843
- * 获取文字的位置信息
1844
- * @param $input 输入框
1845
- * @param selectionStart 起始位置
1846
- * @param selectionEnd 结束位置
1847
- * @example
1848
- * DOMUtils.getTextBoundingRect(document.querySelector("input"));
1849
- */
1850
- getTextBoundingRect(
1851
- $input: HTMLInputElement,
1852
- selectionStart?: number | string,
1853
- selectionEnd?: number | string
1854
- ): DOMRect {
1855
- let DOMUtilsContext = this;
1856
- // Basic parameter validation
1857
- if (!$input || !("value" in $input)) return $input;
1858
- if (selectionStart == null) {
1859
- selectionStart = $input.selectionStart || 0;
1860
- }
1861
- if (selectionEnd == null) {
1862
- selectionEnd = $input.selectionEnd || 0;
1863
- }
1864
- if (typeof selectionStart == "string") selectionStart = parseFloat(selectionStart);
1865
- if (typeof selectionStart != "number" || isNaN(selectionStart)) {
1866
- selectionStart = 0;
1867
- }
1868
- if (selectionStart < 0) selectionStart = 0;
1869
- else selectionStart = Math.min($input.value.length, selectionStart);
1870
- if (typeof selectionEnd == "string") selectionEnd = parseFloat(selectionEnd);
1871
- if (typeof selectionEnd != "number" || isNaN(selectionEnd) || selectionEnd < selectionStart) {
1872
- selectionEnd = selectionStart;
1873
- }
1874
- if (selectionEnd < 0) selectionEnd = 0;
1875
- else selectionEnd = Math.min($input.value.length, selectionEnd);
1870
+ // If available (thus IE), use the createTextRange method
1871
+ if (typeof (<any>$input).createTextRange == "function") {
1872
+ const range = ($input as any).createTextRange();
1873
+ range.collapse(true);
1874
+ range.moveStart("character", selectionStart);
1875
+ range.moveEnd("character", selectionEnd - selectionStart);
1876
+ return range.getBoundingClientRect();
1877
+ }
1878
+ // createTextRange is not supported, create a fake text range
1879
+ const offset = getInputOffset(),
1880
+ width = getInputCSS("width", true),
1881
+ height = getInputCSS("height", true);
1882
+ let topPos = offset.top;
1883
+ let leftPos = offset.left;
1876
1884
 
1877
- // If available (thus IE), use the createTextRange method
1878
- // @ts-ignore
1879
- if (typeof $input.createTextRange == "function") {
1880
- let range = ($input as any).createTextRange();
1881
- range.collapse(true);
1882
- range.moveStart("character", selectionStart);
1883
- range.moveEnd("character", selectionEnd - selectionStart);
1884
- return range.getBoundingClientRect();
1885
- }
1886
- // createTextRange is not supported, create a fake text range
1887
- let offset = getInputOffset(),
1888
- topPos = offset.top,
1889
- leftPos = offset.left,
1890
- width = getInputCSS("width", true),
1891
- height = getInputCSS("height", true);
1885
+ // Styles to simulate a node in an input field
1886
+ let cssDefaultStyles = "white-space:pre;padding:0;margin:0;";
1887
+ const listOfModifiers = [
1888
+ "direction",
1889
+ "font-family",
1890
+ "font-size",
1891
+ "font-size-adjust",
1892
+ "font-variant",
1893
+ "font-weight",
1894
+ "font-style",
1895
+ "letter-spacing",
1896
+ "line-height",
1897
+ "text-align",
1898
+ "text-indent",
1899
+ "text-transform",
1900
+ "word-wrap",
1901
+ "word-spacing",
1902
+ ];
1903
+ topPos += getInputCSS("padding-top", true) as number;
1904
+ topPos += getInputCSS("border-top-width", true) as number;
1905
+ leftPos += getInputCSS("padding-left", true) as number;
1906
+ leftPos += getInputCSS("border-left-width", true) as number;
1907
+ leftPos += 1; //Seems to be necessary
1892
1908
 
1893
- // Styles to simulate a node in an input field
1894
- let cssDefaultStyles = "white-space:pre;padding:0;margin:0;",
1895
- listOfModifiers = [
1896
- "direction",
1897
- "font-family",
1898
- "font-size",
1899
- "font-size-adjust",
1900
- "font-variant",
1901
- "font-weight",
1902
- "font-style",
1903
- "letter-spacing",
1904
- "line-height",
1905
- "text-align",
1906
- "text-indent",
1907
- "text-transform",
1908
- "word-wrap",
1909
- "word-spacing",
1910
- ];
1911
- topPos += getInputCSS("padding-top", true) as number;
1912
- topPos += getInputCSS("border-top-width", true) as number;
1913
- leftPos += getInputCSS("padding-left", true) as number;
1914
- leftPos += getInputCSS("border-left-width", true) as number;
1915
- leftPos += 1; //Seems to be necessary
1909
+ for (let index = 0; index < listOfModifiers.length; index++) {
1910
+ const property = listOfModifiers[index];
1911
+ cssDefaultStyles += property + ":" + getInputCSS(property, false) + ";";
1912
+ }
1913
+ // End of CSS variable checks
1914
+ // 不能为空,不然获取不到高度
1915
+ const text = $input.value || "G",
1916
+ textLen = text.length,
1917
+ fakeClone = DOMUtilsContext.windowApi.document.createElement("div");
1918
+ if (selectionStart > 0) appendPart(0, selectionStart);
1919
+ const fakeRange = appendPart(selectionStart, selectionEnd);
1920
+ if (textLen > selectionEnd) appendPart(selectionEnd, textLen);
1916
1921
 
1917
- for (let index = 0; index < listOfModifiers.length; index++) {
1918
- let property = listOfModifiers[index];
1919
- // @ts-ignore
1920
- cssDefaultStyles += property + ":" + getInputCSS(property) + ";";
1921
- }
1922
- // End of CSS variable checks
1923
- // 不能为空,不然获取不到高度
1924
- let text = $input.value || "G",
1925
- textLen = text.length,
1926
- fakeClone = DOMUtilsContext.windowApi.document.createElement("div");
1927
- if (selectionStart > 0) appendPart(0, selectionStart);
1928
- var fakeRange = appendPart(selectionStart, selectionEnd);
1929
- if (textLen > selectionEnd) appendPart(selectionEnd, textLen);
1922
+ // Styles to inherit the font styles of the element
1923
+ fakeClone.style.cssText = cssDefaultStyles;
1930
1924
 
1931
- // Styles to inherit the font styles of the element
1932
- fakeClone.style.cssText = cssDefaultStyles;
1925
+ // Styles to position the text node at the desired position
1926
+ fakeClone.style.position = "absolute";
1927
+ fakeClone.style.top = topPos + "px";
1928
+ fakeClone.style.left = leftPos + "px";
1929
+ fakeClone.style.width = width + "px";
1930
+ fakeClone.style.height = height + "px";
1931
+ DOMUtilsContext.windowApi.document.body.appendChild(fakeClone);
1932
+ const returnValue = fakeRange.getBoundingClientRect(); //Get rect
1933
1933
 
1934
- // Styles to position the text node at the desired position
1935
- fakeClone.style.position = "absolute";
1936
- fakeClone.style.top = topPos + "px";
1937
- fakeClone.style.left = leftPos + "px";
1938
- fakeClone.style.width = width + "px";
1939
- fakeClone.style.height = height + "px";
1940
- DOMUtilsContext.windowApi.document.body.appendChild(fakeClone);
1941
- var returnValue = fakeRange.getBoundingClientRect(); //Get rect
1934
+ fakeClone?.parentNode?.removeChild(fakeClone); //Remove temp
1935
+ return returnValue;
1942
1936
 
1943
- fakeClone?.parentNode?.removeChild(fakeClone); //Remove temp
1944
- return returnValue;
1945
-
1946
- // Local functions for readability of the previous code
1947
- /**
1948
- *
1949
- * @param start
1950
- * @param end
1951
- * @returns
1952
- */
1953
- function appendPart(start: number, end: number) {
1954
- var span = DOMUtilsContext.windowApi.document.createElement("span");
1955
- span.style.cssText = cssDefaultStyles; //Force styles to prevent unexpected results
1956
- span.textContent = text.substring(start, end);
1957
- fakeClone.appendChild(span);
1958
- return span;
1959
- }
1960
- // Computing offset position
1961
- function getInputOffset() {
1962
- let body = DOMUtilsContext.windowApi.document.body,
1963
- win = DOMUtilsContext.windowApi.document.defaultView!,
1964
- docElem = DOMUtilsContext.windowApi.document.documentElement,
1965
- $box = DOMUtilsContext.windowApi.document.createElement("div");
1966
- $box.style.paddingLeft = $box.style.width = "1px";
1967
- body.appendChild($box);
1968
- var isBoxModel = $box.offsetWidth == 2;
1969
- body.removeChild($box);
1970
- let $boxRect = $input.getBoundingClientRect();
1971
- var clientTop = docElem.clientTop || body.clientTop || 0,
1972
- clientLeft = docElem.clientLeft || body.clientLeft || 0,
1973
- scrollTop = win.pageYOffset || (isBoxModel && docElem.scrollTop) || body.scrollTop,
1974
- scrollLeft = win.pageXOffset || (isBoxModel && docElem.scrollLeft) || body.scrollLeft;
1975
- return {
1976
- top: $boxRect.top + scrollTop - clientTop,
1977
- left: $boxRect.left + scrollLeft - clientLeft,
1978
- };
1979
- }
1980
- /**
1981
- *
1982
- * @param prop
1983
- * @param isNumber
1984
- * @returns
1985
- */
1986
- function getInputCSS(prop: string, isNumber: boolean) {
1987
- var val = DOMUtilsContext.windowApi.document
1988
- .defaultView!.getComputedStyle($input, null)
1989
- .getPropertyValue(prop);
1990
- return isNumber ? parseFloat(val) : val;
1991
- }
1992
- }
1993
- /** 获取 animationend 在各个浏览器的兼容名 */
1994
- getAnimationEndNameList() {
1995
- return DOMUtilsCommonUtils.getAnimationEndNameList();
1996
- }
1997
- /** 获取 transitionend 在各个浏览器的兼容名 */
1998
- getTransitionEndNameList() {
1999
- return DOMUtilsCommonUtils.getTransitionEndNameList();
2000
- }
1937
+ // Local functions for readability of the previous code
1938
+ /**
1939
+ *
1940
+ * @param start
1941
+ * @param end
1942
+ * @returns
1943
+ */
1944
+ function appendPart(start: number, end: number) {
1945
+ const span = DOMUtilsContext.windowApi.document.createElement("span");
1946
+ span.style.cssText = cssDefaultStyles; //Force styles to prevent unexpected results
1947
+ span.textContent = text.substring(start, end);
1948
+ fakeClone.appendChild(span);
1949
+ return span;
1950
+ }
1951
+ // Computing offset position
1952
+ function getInputOffset() {
1953
+ const body = DOMUtilsContext.windowApi.document.body,
1954
+ win = DOMUtilsContext.windowApi.document.defaultView!,
1955
+ docElem = DOMUtilsContext.windowApi.document.documentElement,
1956
+ $box = DOMUtilsContext.windowApi.document.createElement("div");
1957
+ $box.style.paddingLeft = $box.style.width = "1px";
1958
+ body.appendChild($box);
1959
+ const isBoxModel = $box.offsetWidth == 2;
1960
+ body.removeChild($box);
1961
+ const $boxRect = $input.getBoundingClientRect();
1962
+ const clientTop = docElem.clientTop || body.clientTop || 0,
1963
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
1964
+ scrollTop = win.pageYOffset || (isBoxModel && docElem.scrollTop) || body.scrollTop,
1965
+ scrollLeft = win.pageXOffset || (isBoxModel && docElem.scrollLeft) || body.scrollLeft;
1966
+ return {
1967
+ top: $boxRect.top + scrollTop - clientTop,
1968
+ left: $boxRect.left + scrollLeft - clientLeft,
1969
+ };
1970
+ }
1971
+ /**
1972
+ *
1973
+ * @param prop
1974
+ * @param isNumber
1975
+ * @returns
1976
+ */
1977
+ function getInputCSS<T extends boolean>(prop: string, isNumber: T): T extends true ? number : string {
1978
+ const val = DOMUtilsContext.windowApi.document.defaultView!.getComputedStyle($input, null).getPropertyValue(prop);
1979
+ if (isNumber) {
1980
+ return parseFloat(val) as T extends true ? number : string;
1981
+ } else {
1982
+ return val as T extends true ? number : string;
1983
+ }
1984
+ }
1985
+ }
1986
+ /** 获取 animationend 在各个浏览器的兼容名 */
1987
+ getAnimationEndNameList() {
1988
+ return DOMUtilsCommonUtils.getAnimationEndNameList();
1989
+ }
1990
+ /** 获取 transitionend 在各个浏览器的兼容名 */
1991
+ getTransitionEndNameList() {
1992
+ return DOMUtilsCommonUtils.getTransitionEndNameList();
1993
+ }
2001
1994
  }
2002
1995
 
2003
- let domUtils = new DOMUtils();
1996
+ const domUtils = new DOMUtils();
2004
1997
 
2005
1998
  export { domUtils as DOMUtils };