@whitesev/domutils 1.6.6 → 1.6.8

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