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