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