@whitesev/domutils 1.6.6 → 1.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,1174 +2,1153 @@ import { DOMUtilsCommonUtils } from "./DOMUtilsCommonUtils";
2
2
  import { DOMUtilsData } from "./DOMUtilsData";
3
3
  import { OriginPrototype } from "./DOMUtilsOriginPrototype";
4
4
  import type {
5
- DOMUtils_Event,
6
- DOMUtils_EventType,
7
- DOMUtilsElementEventType,
8
- DOMUtilsEventListenerOption,
9
- DOMUtilsEventListenerOptionsAttribute,
5
+ DOMUtils_Event,
6
+ DOMUtils_EventType,
7
+ DOMUtilsElementEventType,
8
+ DOMUtilsEventListenerOption,
9
+ DOMUtilsEventListenerOptionsAttribute,
10
10
  } from "./types/DOMUtilsEvent";
11
11
  import type { DOMUtilsTargetElementType } from "./types/global";
12
12
  import type { WindowApiOption } from "./types/WindowApi";
13
13
  import { WindowApi } from "./WindowApi";
14
14
 
15
15
  export class DOMUtilsEvent {
16
- windowApi: typeof WindowApi.prototype;
17
- constructor(windowApiOption?: WindowApiOption) {
18
- this.windowApi = new WindowApi(windowApiOption);
19
- }
20
- /**
21
- * 绑定事件
22
- * @param element 需要绑定的元素|元素数组|window
23
- * @param eventType 需要监听的事件
24
- * @param callback 绑定事件触发的回调函数
25
- * @param option
26
- * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
27
- * + once 表示事件是否只触发一次。默认为false
28
- * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
29
- * @example
30
- * // 监听元素a.xx的click事件
31
- * DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
32
- * console.log("事件触发",event)
33
- * })
34
- * DOMUtils.on("a.xx","click",(event)=>{
35
- * console.log("事件触发",event)
36
- * })
37
- */
38
- on<T extends DOMUtils_EventType>(
39
- element: DOMUtilsElementEventType,
40
- eventType: T | T[],
41
- callback: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
42
- option?: DOMUtilsEventListenerOption | boolean
43
- ): void;
44
- /**
45
- * 绑定事件
46
- * @param element 需要绑定的元素|元素数组|window
47
- * @param eventType 需要监听的事件
48
- * @param callback 绑定事件触发的回调函数
49
- * @param option
50
- * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
51
- * + once 表示事件是否只触发一次。默认为false
52
- * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
53
- * @example
54
- * // 监听元素a.xx的click事件
55
- * DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
56
- * console.log("事件触发",event)
57
- * })
58
- * DOMUtils.on("a.xx","click",(event)=>{
59
- * console.log("事件触发",event)
60
- * })
61
- */
62
- on<T extends Event>(
63
- element: DOMUtilsElementEventType,
64
- eventType: string | string[],
65
- callback: (this: HTMLElement, event: T) => void,
66
- option?: DOMUtilsEventListenerOption | boolean
67
- ): void;
68
- /**
69
- * 绑定事件
70
- * @param element 需要绑定的元素|元素数组|window
71
- * @param eventType 需要监听的事件
72
- * @param selector 子元素选择器
73
- * @param callback 绑定事件触发的回调函数
74
- * @param option
75
- * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
76
- * + once 表示事件是否只触发一次。默认为false
77
- * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
78
- * @example
79
- * // 监听元素a.xx的click、tap、hover事件
80
- * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event, selectorTarget)=>{
81
- * console.log("事件触发", event, selectorTarget)
82
- * })
83
- * DOMUtils.on("a.xx",["click","tap","hover"],(event, selectorTarget)=>{
84
- * console.log("事件触发", event, selectorTarget)
85
- * })
86
- * @example
87
- * // 监听全局document下的子元素a.xx的click事件
88
- * DOMUtils.on(document,"click tap hover","a.xx",(event, selectorTarget)=>{
89
- * console.log("事件触发", event, selectorTarget)
90
- * })
91
- */
92
- on<T extends DOMUtils_EventType>(
93
- element: DOMUtilsElementEventType,
94
- eventType: T | T[],
95
- selector: string | string[] | undefined | null,
96
- callback: (this: HTMLElement, event: DOMUtils_Event[T], selectorTarget: HTMLElement) => void,
97
- option?: DOMUtilsEventListenerOption | boolean
98
- ): void;
99
- /**
100
- * 绑定事件
101
- * @param element 需要绑定的元素|元素数组|window
102
- * @param eventType 需要监听的事件
103
- * @param selector 子元素选择器
104
- * @param callback 绑定事件触发的回调函数
105
- * @param option
106
- * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
107
- * + once 表示事件是否只触发一次。默认为false
108
- * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
109
- * @example
110
- * // 监听元素a.xx的click、tap、hover事件
111
- * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event, selectorTarget)=>{
112
- * console.log("事件触发", event, selectorTarget)
113
- * })
114
- * DOMUtils.on("a.xx",["click","tap","hover"],(event, selectorTarget)=>{
115
- * console.log("事件触发", event, selectorTarget)
116
- * })
117
- * @example
118
- * // 监听全局document下的子元素a.xx的click事件
119
- * DOMUtils.on(document,"click tap hover","a.xx",(event, selectorTarget)=>{
120
- * console.log("事件触发", event, selectorTarget)
121
- * })
122
- */
123
- on<T extends Event>(
124
- element: DOMUtilsElementEventType,
125
- eventType: string | string[],
126
- selector: string | string[] | undefined | null,
127
- callback: (this: HTMLElement, event: T, selectorTarget: HTMLElement) => void,
128
- option?: DOMUtilsEventListenerOption | boolean
129
- ): void;
130
- on<T extends Event>(
131
- element:
132
- | HTMLElement
133
- | string
134
- | NodeList
135
- | HTMLElement[]
136
- | Window
137
- | Document
138
- | Element
139
- | null
140
- | typeof globalThis,
141
- eventType: DOMUtils_EventType | DOMUtils_EventType[] | string | string[],
142
- selector:
143
- | string
144
- | string[]
145
- | undefined
146
- | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
147
- | null,
148
- callback?:
149
- | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
150
- | DOMUtilsEventListenerOption
151
- | boolean,
152
- option?: DOMUtilsEventListenerOption | boolean
153
- ) {
154
- /**
155
- * 获取option配置
156
- * @param args
157
- * @param startIndex
158
- * @param option
159
- */
160
- function getOption(args: IArguments, startIndex: number, option: DOMUtilsEventListenerOption) {
161
- let currentParam = args[startIndex];
162
- if (typeof currentParam === "boolean") {
163
- option.capture = currentParam;
164
- if (typeof args[startIndex + 1] === "boolean") {
165
- option.once = args[startIndex + 1];
166
- }
167
- if (typeof args[startIndex + 2] === "boolean") {
168
- option.passive = args[startIndex + 2];
169
- }
170
- } else if (
171
- typeof currentParam === "object" &&
172
- ("capture" in currentParam ||
173
- "once" in currentParam ||
174
- "passive" in currentParam ||
175
- "isComposedPath" in currentParam)
176
- ) {
177
- option.capture = currentParam.capture;
178
- option.once = currentParam.once;
179
- option.passive = currentParam.passive;
180
- option.isComposedPath = currentParam.isComposedPath;
181
- }
182
- return option;
183
- }
16
+ windowApi: typeof WindowApi.prototype;
17
+ constructor(windowApiOption?: WindowApiOption) {
18
+ this.windowApi = new WindowApi(windowApiOption);
19
+ }
20
+ /**
21
+ * 绑定事件
22
+ * @param element 需要绑定的元素|元素数组|window
23
+ * @param eventType 需要监听的事件
24
+ * @param callback 绑定事件触发的回调函数
25
+ * @param option
26
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
27
+ * + once 表示事件是否只触发一次。默认为false
28
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
29
+ * @example
30
+ * // 监听元素a.xx的click事件
31
+ * DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
32
+ * console.log("事件触发",event)
33
+ * })
34
+ * DOMUtils.on("a.xx","click",(event)=>{
35
+ * console.log("事件触发",event)
36
+ * })
37
+ */
38
+ on<T extends DOMUtils_EventType>(
39
+ element: DOMUtilsElementEventType,
40
+ eventType: T | T[],
41
+ callback: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
42
+ option?: DOMUtilsEventListenerOption | boolean
43
+ ): void;
44
+ /**
45
+ * 绑定事件
46
+ * @param element 需要绑定的元素|元素数组|window
47
+ * @param eventType 需要监听的事件
48
+ * @param callback 绑定事件触发的回调函数
49
+ * @param option
50
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
51
+ * + once 表示事件是否只触发一次。默认为false
52
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
53
+ * @example
54
+ * // 监听元素a.xx的click事件
55
+ * DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
56
+ * console.log("事件触发",event)
57
+ * })
58
+ * DOMUtils.on("a.xx","click",(event)=>{
59
+ * console.log("事件触发",event)
60
+ * })
61
+ */
62
+ on<T extends Event>(
63
+ element: DOMUtilsElementEventType,
64
+ eventType: string | string[],
65
+ callback: (this: HTMLElement, event: T) => void,
66
+ option?: DOMUtilsEventListenerOption | boolean
67
+ ): void;
68
+ /**
69
+ * 绑定事件
70
+ * @param element 需要绑定的元素|元素数组|window
71
+ * @param eventType 需要监听的事件
72
+ * @param selector 子元素选择器
73
+ * @param callback 绑定事件触发的回调函数
74
+ * @param option
75
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
76
+ * + once 表示事件是否只触发一次。默认为false
77
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
78
+ * @example
79
+ * // 监听元素a.xx的click、tap、hover事件
80
+ * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event, selectorTarget)=>{
81
+ * console.log("事件触发", event, selectorTarget)
82
+ * })
83
+ * DOMUtils.on("a.xx",["click","tap","hover"],(event, selectorTarget)=>{
84
+ * console.log("事件触发", event, selectorTarget)
85
+ * })
86
+ * @example
87
+ * // 监听全局document下的子元素a.xx的click事件
88
+ * DOMUtils.on(document,"click tap hover","a.xx",(event, selectorTarget)=>{
89
+ * console.log("事件触发", event, selectorTarget)
90
+ * })
91
+ */
92
+ on<T extends DOMUtils_EventType>(
93
+ element: DOMUtilsElementEventType,
94
+ eventType: T | T[],
95
+ selector: string | string[] | undefined | null,
96
+ callback: (this: HTMLElement, event: DOMUtils_Event[T], selectorTarget: HTMLElement) => void,
97
+ option?: DOMUtilsEventListenerOption | boolean
98
+ ): void;
99
+ /**
100
+ * 绑定事件
101
+ * @param element 需要绑定的元素|元素数组|window
102
+ * @param eventType 需要监听的事件
103
+ * @param selector 子元素选择器
104
+ * @param callback 绑定事件触发的回调函数
105
+ * @param option
106
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
107
+ * + once 表示事件是否只触发一次。默认为false
108
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
109
+ * @example
110
+ * // 监听元素a.xx的click、tap、hover事件
111
+ * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event, selectorTarget)=>{
112
+ * console.log("事件触发", event, selectorTarget)
113
+ * })
114
+ * DOMUtils.on("a.xx",["click","tap","hover"],(event, selectorTarget)=>{
115
+ * console.log("事件触发", event, selectorTarget)
116
+ * })
117
+ * @example
118
+ * // 监听全局document下的子元素a.xx的click事件
119
+ * DOMUtils.on(document,"click tap hover","a.xx",(event, selectorTarget)=>{
120
+ * console.log("事件触发", event, selectorTarget)
121
+ * })
122
+ */
123
+ on<T extends Event>(
124
+ element: DOMUtilsElementEventType,
125
+ eventType: string | string[],
126
+ selector: string | string[] | undefined | null,
127
+ callback: (this: HTMLElement, event: T, selectorTarget: HTMLElement) => void,
128
+ option?: DOMUtilsEventListenerOption | boolean
129
+ ): void;
130
+ on<T extends Event>(
131
+ element: HTMLElement | string | NodeList | HTMLElement[] | Window | Document | Element | null | typeof globalThis,
132
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string | string[],
133
+ selector:
134
+ | string
135
+ | string[]
136
+ | undefined
137
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
138
+ | null,
139
+ callback?:
140
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
141
+ | DOMUtilsEventListenerOption
142
+ | boolean,
143
+ option?: DOMUtilsEventListenerOption | boolean
144
+ ) {
145
+ /**
146
+ * 获取option配置
147
+ * @param args
148
+ * @param startIndex
149
+ * @param option
150
+ */
151
+ function getOption(args: IArguments, startIndex: number, option: DOMUtilsEventListenerOption) {
152
+ const currentParam = args[startIndex];
153
+ if (typeof currentParam === "boolean") {
154
+ option.capture = currentParam;
155
+ if (typeof args[startIndex + 1] === "boolean") {
156
+ option.once = args[startIndex + 1];
157
+ }
158
+ if (typeof args[startIndex + 2] === "boolean") {
159
+ option.passive = args[startIndex + 2];
160
+ }
161
+ } else if (
162
+ typeof currentParam === "object" &&
163
+ ("capture" in currentParam ||
164
+ "once" in currentParam ||
165
+ "passive" in currentParam ||
166
+ "isComposedPath" in currentParam)
167
+ ) {
168
+ option.capture = currentParam.capture;
169
+ option.once = currentParam.once;
170
+ option.passive = currentParam.passive;
171
+ option.isComposedPath = currentParam.isComposedPath;
172
+ }
173
+ return option;
174
+ }
184
175
 
185
- let DOMUtilsContext = this;
186
- let args = arguments;
187
- if (typeof element === "string") {
188
- element = DOMUtilsContext.selectorAll(element);
189
- }
190
- if (element == null) {
191
- return;
192
- }
193
- let elementList: HTMLElement[] = [];
194
- if (element instanceof NodeList || Array.isArray(element)) {
195
- element = element as HTMLElement[];
196
- elementList = [...element];
197
- } else {
198
- elementList.push(element as HTMLElement);
199
- }
200
- // 事件名
201
- let eventTypeList: string[] = [];
202
- if (Array.isArray(eventType)) {
203
- eventTypeList = eventTypeList.concat(
204
- eventType.filter(
205
- (eventTypeItem) => typeof eventTypeItem === "string" && eventTypeItem.toString() !== ""
206
- )
207
- );
208
- } else if (typeof eventType === "string") {
209
- eventTypeList = eventTypeList.concat(
210
- eventType.split(" ").filter((eventTypeItem) => eventTypeItem !== "")
211
- );
212
- }
213
- // 子元素选择器
214
- let selectorList: string[] = [];
215
- if (Array.isArray(selector)) {
216
- selectorList = selectorList.concat(
217
- selector.filter((selectorItem) => typeof selectorItem === "string" && selectorItem.toString() !== "")
218
- );
219
- } else if (typeof selector === "string") {
220
- selectorList.push(selector);
221
- }
222
- // 事件回调
223
- let listenerCallBack: (this: HTMLElement, event: Event, selectorTarget?: HTMLElement) => void =
224
- callback as any;
225
- // 事件配置
226
- let listenerOption: DOMUtilsEventListenerOption = {
227
- capture: false,
228
- once: false,
229
- passive: false,
230
- isComposedPath: false,
231
- };
232
- if (typeof selector === "function") {
233
- // 这是为没有selector的情况
234
- // 那么它就是callback
235
- listenerCallBack = selector as any;
236
- listenerOption = getOption(args, 3, listenerOption);
237
- } else {
238
- // 这是存在selector的情况
239
- listenerOption = getOption(args, 4, listenerOption);
240
- }
241
- /**
242
- * 如果是once,那么删除该监听和元素上的事件和监听
243
- */
244
- function checkOptionOnceToRemoveEventListener() {
245
- if (listenerOption.once) {
246
- DOMUtilsContext.off(element, eventType as any, selector as any, callback as any, option);
247
- }
248
- }
249
- elementList.forEach((elementItem) => {
250
- /**
251
- * 事件回调
252
- * @param event
253
- */
254
- function domUtilsEventCallBack(event: Event) {
255
- if (selectorList.length) {
256
- /* 存在子元素选择器 */
257
- // 这时候的this和target都是子元素选择器的元素
258
- let eventTarget = listenerOption.isComposedPath
259
- ? (event.composedPath()[0] as HTMLElement)
260
- : (event.target as HTMLElement);
261
- let totalParent = elementItem;
262
- if (DOMUtilsCommonUtils.isWin(totalParent)) {
263
- if (totalParent === (DOMUtilsContext.windowApi.document as any as HTMLElement)) {
264
- totalParent = DOMUtilsContext.windowApi.document.documentElement;
265
- }
266
- }
267
- let findValue = selectorList.find((selectorItem) => {
268
- // 判断目标元素是否匹配选择器
269
- if (DOMUtilsContext.matches(eventTarget, selectorItem)) {
270
- /* 当前目标可以被selector所匹配到 */
271
- return true;
272
- }
273
- /* 在上层与主元素之间寻找可以被selector所匹配到的 */
274
- let $closestMatches = DOMUtilsContext.closest<HTMLElement>(eventTarget, selectorItem);
275
- if ($closestMatches && totalParent?.contains($closestMatches)) {
276
- eventTarget = $closestMatches;
277
- return true;
278
- }
279
- return false;
280
- });
281
- if (findValue) {
282
- // 这里尝试使用defineProperty修改event的target值
283
- try {
284
- OriginPrototype.Object.defineProperty(event, "target", {
285
- get() {
286
- return eventTarget;
287
- },
288
- });
289
- } catch (error) {}
290
- listenerCallBack.call(eventTarget, event as any, eventTarget);
291
- checkOptionOnceToRemoveEventListener();
292
- }
293
- } else {
294
- // 这时候的this指向监听的元素
295
- listenerCallBack.call(elementItem, event as any);
296
- checkOptionOnceToRemoveEventListener();
297
- }
298
- }
176
+ const DOMUtilsContext = this;
177
+ // eslint-disable-next-line prefer-rest-params
178
+ const args = arguments;
179
+ if (typeof element === "string") {
180
+ element = DOMUtilsContext.selectorAll(element);
181
+ }
182
+ if (element == null) {
183
+ return;
184
+ }
185
+ let elementList: HTMLElement[] = [];
186
+ if (element instanceof NodeList || Array.isArray(element)) {
187
+ element = element as HTMLElement[];
188
+ elementList = [...element];
189
+ } else {
190
+ elementList.push(element as HTMLElement);
191
+ }
192
+ // 事件名
193
+ let eventTypeList: string[] = [];
194
+ if (Array.isArray(eventType)) {
195
+ eventTypeList = eventTypeList.concat(
196
+ eventType.filter((eventTypeItem) => typeof eventTypeItem === "string" && eventTypeItem.toString() !== "")
197
+ );
198
+ } else if (typeof eventType === "string") {
199
+ eventTypeList = eventTypeList.concat(eventType.split(" ").filter((eventTypeItem) => eventTypeItem !== ""));
200
+ }
201
+ // 子元素选择器
202
+ let selectorList: string[] = [];
203
+ if (Array.isArray(selector)) {
204
+ selectorList = selectorList.concat(
205
+ selector.filter((selectorItem) => typeof selectorItem === "string" && selectorItem.toString() !== "")
206
+ );
207
+ } else if (typeof selector === "string") {
208
+ selectorList.push(selector);
209
+ }
210
+ // 事件回调
211
+ let listenerCallBack: (this: HTMLElement, event: Event, selectorTarget?: HTMLElement) => void = callback as any;
212
+ // 事件配置
213
+ let listenerOption: DOMUtilsEventListenerOption = {
214
+ capture: false,
215
+ once: false,
216
+ passive: false,
217
+ isComposedPath: false,
218
+ };
219
+ if (typeof selector === "function") {
220
+ // 这是为没有selector的情况
221
+ // 那么它就是callback
222
+ listenerCallBack = selector as any;
223
+ listenerOption = getOption(args, 3, listenerOption);
224
+ } else {
225
+ // 这是存在selector的情况
226
+ listenerOption = getOption(args, 4, listenerOption);
227
+ }
228
+ /**
229
+ * 如果是once,那么删除该监听和元素上的事件和监听
230
+ */
231
+ function checkOptionOnceToRemoveEventListener() {
232
+ if (listenerOption.once) {
233
+ DOMUtilsContext.off(element, eventType as any, selector as any, callback as any, option);
234
+ }
235
+ }
236
+ elementList.forEach((elementItem) => {
237
+ /**
238
+ * 事件回调
239
+ * @param event
240
+ */
241
+ function domUtilsEventCallBack(event: Event) {
242
+ if (selectorList.length) {
243
+ /* 存在子元素选择器 */
244
+ // 这时候的this和target都是子元素选择器的元素
245
+ let eventTarget = listenerOption.isComposedPath
246
+ ? (event.composedPath()[0] as HTMLElement)
247
+ : (event.target as HTMLElement);
248
+ let totalParent = elementItem;
249
+ if (DOMUtilsCommonUtils.isWin(totalParent)) {
250
+ if (totalParent === (DOMUtilsContext.windowApi.document as any as HTMLElement)) {
251
+ totalParent = DOMUtilsContext.windowApi.document.documentElement;
252
+ }
253
+ }
254
+ const findValue = selectorList.find((selectorItem) => {
255
+ // 判断目标元素是否匹配选择器
256
+ if (DOMUtilsContext.matches(eventTarget, selectorItem)) {
257
+ /* 当前目标可以被selector所匹配到 */
258
+ return true;
259
+ }
260
+ /* 在上层与主元素之间寻找可以被selector所匹配到的 */
261
+ const $closestMatches = DOMUtilsContext.closest<HTMLElement>(eventTarget, selectorItem);
262
+ if ($closestMatches && totalParent?.contains($closestMatches)) {
263
+ eventTarget = $closestMatches;
264
+ return true;
265
+ }
266
+ return false;
267
+ });
268
+ if (findValue) {
269
+ // 这里尝试使用defineProperty修改event的target值
270
+ try {
271
+ OriginPrototype.Object.defineProperty(event, "target", {
272
+ get() {
273
+ return eventTarget;
274
+ },
275
+ });
276
+ } catch {
277
+ // TODO
278
+ }
279
+ listenerCallBack.call(eventTarget, event as any, eventTarget);
280
+ checkOptionOnceToRemoveEventListener();
281
+ }
282
+ } else {
283
+ // 这时候的this指向监听的元素
284
+ listenerCallBack.call(elementItem, event as any);
285
+ checkOptionOnceToRemoveEventListener();
286
+ }
287
+ }
299
288
 
300
- /* 遍历事件名设置元素事件 */
301
- eventTypeList.forEach((eventName) => {
302
- elementItem.addEventListener(eventName, domUtilsEventCallBack, listenerOption);
303
- /* 获取对象上的事件 */
304
- let elementEvents: {
305
- [k: string]: DOMUtilsEventListenerOptionsAttribute[];
306
- } = Reflect.get(elementItem, DOMUtilsData.SymbolEvents) || {};
307
- /* 初始化对象上的xx事件 */
308
- elementEvents[eventName] = elementEvents[eventName] || [];
309
- elementEvents[eventName].push({
310
- selector: selectorList,
311
- option: listenerOption,
312
- callback: domUtilsEventCallBack,
313
- originCallBack: listenerCallBack,
314
- });
315
- /* 覆盖事件 */
316
- Reflect.set(elementItem, DOMUtilsData.SymbolEvents, elementEvents);
317
- });
318
- });
319
- }
320
- /**
321
- * 取消绑定事件
322
- * @param element 需要取消绑定的元素|元素数组
323
- * @param eventType 需要取消监听的事件
324
- * @param callback 通过DOMUtils.on绑定的事件函数
325
- * @param option
326
- * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
327
- * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
328
- * @example
329
- * // 取消监听元素a.xx所有的click事件
330
- * DOMUtils.off(document.querySelector("a.xx"),"click")
331
- * DOMUtils.off("a.xx","click")
332
- */
333
- off<T extends DOMUtils_EventType>(
334
- element: DOMUtilsElementEventType,
335
- eventType: T | T[],
336
- callback?: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
337
- option?: EventListenerOptions | boolean,
338
- filter?: (
339
- value: DOMUtilsEventListenerOptionsAttribute,
340
- index: number,
341
- array: DOMUtilsEventListenerOptionsAttribute[]
342
- ) => boolean
343
- ): void;
344
- /**
345
- * 取消绑定事件
346
- * @param element 需要取消绑定的元素|元素数组
347
- * @param eventType 需要取消监听的事件
348
- * @param callback 通过DOMUtils.on绑定的事件函数
349
- * @param option
350
- * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
351
- * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
352
- * @example
353
- * // 取消监听元素a.xx的click事件
354
- * DOMUtils.off(document.querySelector("a.xx"),"click")
355
- * DOMUtils.off("a.xx","click")
356
- */
357
- off<T extends Event>(
358
- element: DOMUtilsElementEventType,
359
- eventType: string | string[],
360
- callback?: (this: HTMLElement, event: T) => void,
361
- option?: EventListenerOptions | boolean,
362
- filter?: (
363
- value: DOMUtilsEventListenerOptionsAttribute,
364
- index: number,
365
- array: DOMUtilsEventListenerOptionsAttribute[]
366
- ) => boolean
367
- ): void;
368
- /**
369
- * 取消绑定事件
370
- * @param element 需要取消绑定的元素|元素数组
371
- * @param eventType 需要取消监听的事件
372
- * @param selector 子元素选择器
373
- * @param callback 通过DOMUtils.on绑定的事件函数
374
- * @param option
375
- * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
376
- * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
377
- * @example
378
- * // 取消监听元素a.xx的click、tap、hover事件
379
- * DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
380
- * DOMUtils.off("a.xx",["click","tap","hover"])
381
- */
382
- off<T extends DOMUtils_EventType>(
383
- element: DOMUtilsElementEventType,
384
- eventType: T | T[],
385
- selector?: string | string[] | undefined | null,
386
- callback?: (this: HTMLElement, event: DOMUtils_Event[T], selectorTarget: HTMLElement) => void,
387
- option?: EventListenerOptions | boolean,
388
- filter?: (
389
- value: DOMUtilsEventListenerOptionsAttribute,
390
- index: number,
391
- array: DOMUtilsEventListenerOptionsAttribute[]
392
- ) => boolean
393
- ): void;
394
- /**
395
- * 取消绑定事件
396
- * @param element 需要取消绑定的元素|元素数组
397
- * @param eventType 需要取消监听的事件
398
- * @param selector 子元素选择器
399
- * @param callback 通过DOMUtils.on绑定的事件函数
400
- * @param option
401
- * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
402
- * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
403
- * @example
404
- * // 取消监听元素a.xx的click、tap、hover事件
405
- * DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
406
- * DOMUtils.off("a.xx",["click","tap","hover"])
407
- */
408
- off<T extends Event>(
409
- element: DOMUtilsElementEventType,
410
- eventType: string | string[],
411
- selector?: string | string[] | undefined | null,
412
- callback?: (this: HTMLElement, event: T, selectorTarget: HTMLElement) => void,
413
- option?: EventListenerOptions | boolean,
414
- filter?: (
415
- value: DOMUtilsEventListenerOptionsAttribute,
416
- index: number,
417
- array: DOMUtilsEventListenerOptionsAttribute[]
418
- ) => boolean
419
- ): void;
420
- off<T extends Event>(
421
- element:
422
- | HTMLElement
423
- | string
424
- | NodeList
425
- | HTMLElement[]
426
- | Window
427
- | Document
428
- | Element
429
- | null
430
- | typeof globalThis,
431
- eventType: DOMUtils_EventType | DOMUtils_EventType[] | string | string[],
432
- selector:
433
- | string
434
- | string[]
435
- | undefined
436
- | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
437
- | null,
438
- callback?:
439
- | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
440
- | EventListenerOptions
441
- | boolean,
442
- option?:
443
- | EventListenerOptions
444
- | boolean
445
- | ((
446
- value: DOMUtilsEventListenerOptionsAttribute,
447
- index: number,
448
- array: DOMUtilsEventListenerOptionsAttribute[]
449
- ) => boolean),
450
- filter?: (
451
- value: DOMUtilsEventListenerOptionsAttribute,
452
- index: number,
453
- array: DOMUtilsEventListenerOptionsAttribute[]
454
- ) => boolean
455
- ) {
456
- /**
457
- * 获取option配置
458
- * @param args1
459
- * @param startIndex
460
- * @param option
461
- */
462
- function getOption(args1: IArguments, startIndex: number, option: EventListenerOptions) {
463
- let currentParam: EventListenerOptions | boolean = args1[startIndex];
464
- if (typeof currentParam === "boolean") {
465
- option.capture = currentParam;
466
- } else if (typeof currentParam === "object" && "capture" in currentParam) {
467
- option.capture = currentParam.capture;
468
- }
469
- return option;
470
- }
471
- let DOMUtilsContext = this;
472
- let args = arguments;
473
- if (typeof element === "string") {
474
- element = DOMUtilsContext.selectorAll(element);
475
- }
476
- if (element == null) {
477
- return;
478
- }
479
- let elementList: HTMLElement[] = [];
480
- if (element instanceof NodeList || Array.isArray(element)) {
481
- element = element as HTMLElement[];
482
- elementList = [...element];
483
- } else {
484
- elementList.push(element as HTMLElement);
485
- }
486
- let eventTypeList: string[] = [];
487
- if (Array.isArray(eventType)) {
488
- eventTypeList = eventTypeList.concat(
489
- eventType.filter(
490
- (eventTypeItem) => typeof eventTypeItem === "string" && eventTypeItem.toString() !== ""
491
- )
492
- );
493
- } else if (typeof eventType === "string") {
494
- eventTypeList = eventTypeList.concat(
495
- eventType.split(" ").filter((eventTypeItem) => eventTypeItem !== "")
496
- );
497
- }
498
- // 子元素选择器
499
- let selectorList: string[] = [];
500
- if (Array.isArray(selector)) {
501
- selectorList = selectorList.concat(
502
- selector.filter((selectorItem) => typeof selectorItem === "string" && selectorItem.toString() !== "")
503
- );
504
- } else if (typeof selector === "string") {
505
- selectorList.push(selector);
506
- }
507
- /**
508
- * 事件的回调函数
509
- */
510
- let listenerCallBack: (this: HTMLElement, event: T, selectorTarget: HTMLElement) => void =
511
- callback as any;
289
+ /* 遍历事件名设置元素事件 */
290
+ eventTypeList.forEach((eventName) => {
291
+ elementItem.addEventListener(eventName, domUtilsEventCallBack, listenerOption);
292
+ /* 获取对象上的事件 */
293
+ const elementEvents: {
294
+ [k: string]: DOMUtilsEventListenerOptionsAttribute[];
295
+ } = Reflect.get(elementItem, DOMUtilsData.SymbolEvents) || {};
296
+ /* 初始化对象上的xx事件 */
297
+ elementEvents[eventName] = elementEvents[eventName] || [];
298
+ elementEvents[eventName].push({
299
+ selector: selectorList,
300
+ option: listenerOption,
301
+ callback: domUtilsEventCallBack,
302
+ originCallBack: listenerCallBack,
303
+ });
304
+ /* 覆盖事件 */
305
+ Reflect.set(elementItem, DOMUtilsData.SymbolEvents, elementEvents);
306
+ });
307
+ });
308
+ }
309
+ /**
310
+ * 取消绑定事件
311
+ * @param element 需要取消绑定的元素|元素数组
312
+ * @param eventType 需要取消监听的事件
313
+ * @param callback 通过DOMUtils.on绑定的事件函数
314
+ * @param option
315
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
316
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
317
+ * @example
318
+ * // 取消监听元素a.xx所有的click事件
319
+ * DOMUtils.off(document.querySelector("a.xx"),"click")
320
+ * DOMUtils.off("a.xx","click")
321
+ */
322
+ off<T extends DOMUtils_EventType>(
323
+ element: DOMUtilsElementEventType,
324
+ eventType: T | T[],
325
+ callback?: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
326
+ option?: EventListenerOptions | boolean,
327
+ filter?: (
328
+ value: DOMUtilsEventListenerOptionsAttribute,
329
+ index: number,
330
+ array: DOMUtilsEventListenerOptionsAttribute[]
331
+ ) => boolean
332
+ ): void;
333
+ /**
334
+ * 取消绑定事件
335
+ * @param element 需要取消绑定的元素|元素数组
336
+ * @param eventType 需要取消监听的事件
337
+ * @param callback 通过DOMUtils.on绑定的事件函数
338
+ * @param option
339
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
340
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
341
+ * @example
342
+ * // 取消监听元素a.xx的click事件
343
+ * DOMUtils.off(document.querySelector("a.xx"),"click")
344
+ * DOMUtils.off("a.xx","click")
345
+ */
346
+ off<T extends Event>(
347
+ element: DOMUtilsElementEventType,
348
+ eventType: string | string[],
349
+ callback?: (this: HTMLElement, event: T) => void,
350
+ option?: EventListenerOptions | boolean,
351
+ filter?: (
352
+ value: DOMUtilsEventListenerOptionsAttribute,
353
+ index: number,
354
+ array: DOMUtilsEventListenerOptionsAttribute[]
355
+ ) => boolean
356
+ ): void;
357
+ /**
358
+ * 取消绑定事件
359
+ * @param element 需要取消绑定的元素|元素数组
360
+ * @param eventType 需要取消监听的事件
361
+ * @param selector 子元素选择器
362
+ * @param callback 通过DOMUtils.on绑定的事件函数
363
+ * @param option
364
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
365
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
366
+ * @example
367
+ * // 取消监听元素a.xx的click、tap、hover事件
368
+ * DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
369
+ * DOMUtils.off("a.xx",["click","tap","hover"])
370
+ */
371
+ off<T extends DOMUtils_EventType>(
372
+ element: DOMUtilsElementEventType,
373
+ eventType: T | T[],
374
+ selector?: string | string[] | undefined | null,
375
+ callback?: (this: HTMLElement, event: DOMUtils_Event[T], selectorTarget: HTMLElement) => void,
376
+ option?: EventListenerOptions | boolean,
377
+ filter?: (
378
+ value: DOMUtilsEventListenerOptionsAttribute,
379
+ index: number,
380
+ array: DOMUtilsEventListenerOptionsAttribute[]
381
+ ) => boolean
382
+ ): void;
383
+ /**
384
+ * 取消绑定事件
385
+ * @param element 需要取消绑定的元素|元素数组
386
+ * @param eventType 需要取消监听的事件
387
+ * @param selector 子元素选择器
388
+ * @param callback 通过DOMUtils.on绑定的事件函数
389
+ * @param option
390
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
391
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
392
+ * @example
393
+ * // 取消监听元素a.xx的click、tap、hover事件
394
+ * DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
395
+ * DOMUtils.off("a.xx",["click","tap","hover"])
396
+ */
397
+ off<T extends Event>(
398
+ element: DOMUtilsElementEventType,
399
+ eventType: string | string[],
400
+ selector?: string | string[] | undefined | null,
401
+ callback?: (this: HTMLElement, event: T, selectorTarget: HTMLElement) => void,
402
+ option?: EventListenerOptions | boolean,
403
+ filter?: (
404
+ value: DOMUtilsEventListenerOptionsAttribute,
405
+ index: number,
406
+ array: DOMUtilsEventListenerOptionsAttribute[]
407
+ ) => boolean
408
+ ): void;
409
+ off<T extends Event>(
410
+ element: HTMLElement | string | NodeList | HTMLElement[] | Window | Document | Element | null | typeof globalThis,
411
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string | string[],
412
+ selector:
413
+ | string
414
+ | string[]
415
+ | undefined
416
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
417
+ | null,
418
+ callback?: ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void) | EventListenerOptions | boolean,
419
+ option?:
420
+ | EventListenerOptions
421
+ | boolean
422
+ | ((
423
+ value: DOMUtilsEventListenerOptionsAttribute,
424
+ index: number,
425
+ array: DOMUtilsEventListenerOptionsAttribute[]
426
+ ) => boolean),
427
+ filter?: (
428
+ value: DOMUtilsEventListenerOptionsAttribute,
429
+ index: number,
430
+ array: DOMUtilsEventListenerOptionsAttribute[]
431
+ ) => boolean
432
+ ) {
433
+ /**
434
+ * 获取option配置
435
+ * @param args1
436
+ * @param startIndex
437
+ * @param option
438
+ */
439
+ function getOption(args1: IArguments, startIndex: number, option: EventListenerOptions) {
440
+ const currentParam: EventListenerOptions | boolean = args1[startIndex];
441
+ if (typeof currentParam === "boolean") {
442
+ option.capture = currentParam;
443
+ } else if (typeof currentParam === "object" && currentParam != null && "capture" in currentParam) {
444
+ option.capture = currentParam.capture;
445
+ }
446
+ return option;
447
+ }
448
+ const DOMUtilsContext = this;
449
+ // eslint-disable-next-line prefer-rest-params
450
+ const args = arguments;
451
+ if (typeof element === "string") {
452
+ element = DOMUtilsContext.selectorAll(element);
453
+ }
454
+ if (element == null) {
455
+ return;
456
+ }
457
+ let elementList: HTMLElement[] = [];
458
+ if (element instanceof NodeList || Array.isArray(element)) {
459
+ element = element as HTMLElement[];
460
+ elementList = [...element];
461
+ } else {
462
+ elementList.push(element as HTMLElement);
463
+ }
464
+ let eventTypeList: string[] = [];
465
+ if (Array.isArray(eventType)) {
466
+ eventTypeList = eventTypeList.concat(
467
+ eventType.filter((eventTypeItem) => typeof eventTypeItem === "string" && eventTypeItem.toString() !== "")
468
+ );
469
+ } else if (typeof eventType === "string") {
470
+ eventTypeList = eventTypeList.concat(eventType.split(" ").filter((eventTypeItem) => eventTypeItem !== ""));
471
+ }
472
+ // 子元素选择器
473
+ let selectorList: string[] = [];
474
+ if (Array.isArray(selector)) {
475
+ selectorList = selectorList.concat(
476
+ selector.filter((selectorItem) => typeof selectorItem === "string" && selectorItem.toString() !== "")
477
+ );
478
+ } else if (typeof selector === "string") {
479
+ selectorList.push(selector);
480
+ }
481
+ /**
482
+ * 事件的回调函数
483
+ */
484
+ let listenerCallBack: (this: HTMLElement, event: T, selectorTarget: HTMLElement) => void = callback as any;
512
485
 
513
- /**
514
- * 事件的配置
515
- */
516
- let listenerOption: EventListenerOptions = {
517
- capture: false,
518
- };
519
- if (typeof selector === "function") {
520
- // 这是为没有selector的情况
521
- // 那么它就是callback
522
- listenerCallBack = selector;
523
- listenerOption = getOption(args, 3, listenerOption);
524
- } else {
525
- // 这是存在selector的情况
526
- listenerOption = getOption(args, 4, listenerOption);
527
- }
528
- // 是否移除所有事件
529
- let isRemoveAll = false;
530
- if (args.length === 2) {
531
- // 目标函数、事件名
532
- isRemoveAll = true;
533
- } else if ((args.length === 3 && typeof args[2] === "string") || Array.isArray(args[2])) {
534
- // 目标函数、事件名、子元素选择器
535
- isRemoveAll = true;
536
- }
537
- elementList.forEach((elementItem) => {
538
- /* 获取对象上的事件 */
539
- let elementEvents: {
540
- [key: string]: DOMUtilsEventListenerOptionsAttribute[];
541
- } = Reflect.get(elementItem, DOMUtilsData.SymbolEvents) || {};
542
- eventTypeList.forEach((eventName) => {
543
- let handlers = elementEvents[eventName] || [];
544
- if (typeof filter === "function") {
545
- handlers = handlers.filter(filter);
546
- }
547
- for (let index = 0; index < handlers.length; index++) {
548
- let handler = handlers[index];
549
- let flag = true;
550
- if (flag && listenerCallBack && handler.originCallBack !== listenerCallBack) {
551
- // callback不同
552
- flag = false;
553
- }
554
- if (flag && selectorList.length && Array.isArray(handler.selector)) {
555
- if (JSON.stringify(handler.selector) !== JSON.stringify(selectorList)) {
556
- // 子元素选择器不同
557
- flag = false;
558
- }
559
- }
560
- if (flag && listenerOption.capture !== handler.option.capture) {
561
- // 事件的配置项不同
562
- flag = false;
563
- }
564
- if (flag || isRemoveAll) {
565
- elementItem.removeEventListener(eventName, handler.callback, handler.option);
566
- handlers.splice(index--, 1);
567
- }
568
- }
569
- if (handlers.length === 0) {
570
- /* 如果没有任意的handler,那么删除该属性 */
571
- DOMUtilsCommonUtils.delete(elementEvents, eventType);
572
- }
573
- });
574
- Reflect.set(elementItem, DOMUtilsData.SymbolEvents, elementEvents);
575
- });
576
- }
577
- /**
578
- * 取消绑定所有的事件
579
- * @param element 需要取消绑定的元素|元素数组
580
- * @param eventType (可选)需要取消监听的事件
581
- */
582
- offAll(element: DOMUtilsElementEventType, eventType?: string): void;
583
- /**
584
- * 取消绑定所有的事件
585
- * @param element 需要取消绑定的元素|元素数组
586
- * @param eventType (可选)需要取消监听的事件
587
- */
588
- offAll(element: DOMUtilsElementEventType, eventType?: DOMUtils_EventType | DOMUtils_EventType[]): void;
589
- /**
590
- * 取消绑定所有的事件
591
- * @param element 需要取消绑定的元素|元素数组
592
- * @param eventType (可选)需要取消监听的事件
593
- */
594
- offAll(element: DOMUtilsElementEventType, eventType?: DOMUtils_EventType | DOMUtils_EventType[] | string) {
595
- let DOMUtilsContext = this;
596
- if (typeof element === "string") {
597
- element = DOMUtilsContext.selectorAll(element);
598
- }
599
- if (element == null) {
600
- return;
601
- }
602
- let elementList: HTMLElement[] = [];
603
- if (element instanceof NodeList || Array.isArray(element)) {
604
- elementList = [...(element as HTMLElement[])];
605
- } else {
606
- elementList.push(element as HTMLElement);
607
- }
486
+ /**
487
+ * 事件的配置
488
+ */
489
+ let listenerOption: EventListenerOptions = {
490
+ capture: false,
491
+ };
492
+ if (typeof selector === "function") {
493
+ // 这是为没有selector的情况
494
+ // 那么它就是callback
495
+ listenerCallBack = selector;
496
+ listenerOption = getOption(args, 3, listenerOption);
497
+ } else {
498
+ // 这是存在selector的情况
499
+ listenerOption = getOption(args, 4, listenerOption);
500
+ }
501
+ // 是否移除所有事件
502
+ let isRemoveAll = false;
503
+ if (args.length === 2) {
504
+ // 目标函数、事件名
505
+ isRemoveAll = true;
506
+ } else if ((args.length === 3 && typeof args[2] === "string") || Array.isArray(args[2])) {
507
+ // 目标函数、事件名、子元素选择器
508
+ isRemoveAll = true;
509
+ }
510
+ if (args.length === 5 && typeof args[4] === "function" && typeof filter !== "function") {
511
+ // 目标函数、事件名、回调函数、事件配置、过滤函数
512
+ filter = option as (
513
+ value: DOMUtilsEventListenerOptionsAttribute,
514
+ index: number,
515
+ array: DOMUtilsEventListenerOptionsAttribute[]
516
+ ) => boolean;
517
+ }
518
+ elementList.forEach((elementItem) => {
519
+ /* 获取对象上的事件 */
520
+ const elementEvents: {
521
+ [key: string]: DOMUtilsEventListenerOptionsAttribute[];
522
+ } = Reflect.get(elementItem, DOMUtilsData.SymbolEvents) || {};
523
+ eventTypeList.forEach((eventName) => {
524
+ const handlers = elementEvents[eventName] || [];
525
+ const filterHandler = typeof filter === "function" ? handlers.filter(filter) : handlers;
526
+ for (let index = 0; index < filterHandler.length; index++) {
527
+ const handler = filterHandler[index];
528
+ let flag = true;
529
+ if (flag && listenerCallBack && handler.originCallBack !== listenerCallBack) {
530
+ // callback不同
531
+ flag = false;
532
+ }
533
+ if (flag && selectorList.length && Array.isArray(handler.selector)) {
534
+ if (JSON.stringify(handler.selector) !== JSON.stringify(selectorList)) {
535
+ // 子元素选择器不同
536
+ flag = false;
537
+ }
538
+ }
539
+ if (
540
+ flag &&
541
+ typeof handler.option.capture === "boolean" &&
542
+ listenerOption.capture !== handler.option.capture
543
+ ) {
544
+ // 事件的配置项不同
545
+ flag = false;
546
+ }
547
+ if (flag || isRemoveAll) {
548
+ elementItem.removeEventListener(eventName, handler.callback, handler.option);
549
+ const findIndex = handlers.findIndex((item) => item === handler);
550
+ if (findIndex !== -1) {
551
+ handlers.splice(findIndex, 1);
552
+ }
553
+ }
554
+ }
555
+ if (handlers.length === 0) {
556
+ /* 如果没有任意的handler,那么删除该属性 */
557
+ DOMUtilsCommonUtils.delete(elementEvents, eventType);
558
+ }
559
+ });
560
+ Reflect.set(elementItem, DOMUtilsData.SymbolEvents, elementEvents);
561
+ });
562
+ }
563
+ /**
564
+ * 取消绑定所有的事件
565
+ * @param element 需要取消绑定的元素|元素数组
566
+ * @param eventType (可选)需要取消监听的事件
567
+ */
568
+ offAll(element: DOMUtilsElementEventType, eventType?: string): void;
569
+ /**
570
+ * 取消绑定所有的事件
571
+ * @param element 需要取消绑定的元素|元素数组
572
+ * @param eventType (可选)需要取消监听的事件
573
+ */
574
+ offAll(element: DOMUtilsElementEventType, eventType?: DOMUtils_EventType | DOMUtils_EventType[]): void;
575
+ /**
576
+ * 取消绑定所有的事件
577
+ * @param element 需要取消绑定的元素|元素数组
578
+ * @param eventType (可选)需要取消监听的事件
579
+ */
580
+ offAll(element: DOMUtilsElementEventType, eventType?: DOMUtils_EventType | DOMUtils_EventType[] | string) {
581
+ const DOMUtilsContext = this;
582
+ if (typeof element === "string") {
583
+ element = DOMUtilsContext.selectorAll(element);
584
+ }
585
+ if (element == null) {
586
+ return;
587
+ }
588
+ let elementList: HTMLElement[] = [];
589
+ if (element instanceof NodeList || Array.isArray(element)) {
590
+ elementList = [...(element as HTMLElement[])];
591
+ } else {
592
+ elementList.push(element as HTMLElement);
593
+ }
608
594
 
609
- let eventTypeList: string[] = [];
610
- if (Array.isArray(eventType)) {
611
- eventTypeList = eventTypeList.concat(eventType as string[]);
612
- } else if (typeof eventType === "string") {
613
- eventTypeList = eventTypeList.concat(eventType.split(" "));
614
- }
615
- elementList.forEach((elementItem) => {
616
- Object.getOwnPropertySymbols(elementItem).forEach((symbolEvents) => {
617
- if (!symbolEvents.toString().startsWith("Symbol(events_")) {
618
- return;
619
- }
620
- let elementEvents = (elementItem as any)[symbolEvents] || {};
621
- let iterEventNameList = eventTypeList.length ? eventTypeList : Object.keys(elementEvents);
622
- iterEventNameList.forEach((eventName) => {
623
- let handlers: DOMUtilsEventListenerOptionsAttribute[] = elementEvents[eventName];
624
- if (!handlers) {
625
- return;
626
- }
627
- for (const handler of handlers) {
628
- elementItem.removeEventListener(eventName, handler.callback, {
629
- capture: handler["option"]["capture"],
630
- });
631
- }
632
- let events = Reflect.get(elementItem, symbolEvents);
633
- DOMUtilsCommonUtils.delete(events, eventName);
634
- });
635
- });
636
- });
637
- }
595
+ let eventTypeList: string[] = [];
596
+ if (Array.isArray(eventType)) {
597
+ eventTypeList = eventTypeList.concat(eventType as string[]);
598
+ } else if (typeof eventType === "string") {
599
+ eventTypeList = eventTypeList.concat(eventType.split(" "));
600
+ }
601
+ elementList.forEach((elementItem) => {
602
+ Object.getOwnPropertySymbols(elementItem).forEach((symbolEvents) => {
603
+ if (!symbolEvents.toString().startsWith("Symbol(events_")) {
604
+ return;
605
+ }
606
+ const elementEvents = (elementItem as any)[symbolEvents] || {};
607
+ const iterEventNameList = eventTypeList.length ? eventTypeList : Object.keys(elementEvents);
608
+ iterEventNameList.forEach((eventName) => {
609
+ const handlers: DOMUtilsEventListenerOptionsAttribute[] = elementEvents[eventName];
610
+ if (!handlers) {
611
+ return;
612
+ }
613
+ for (const handler of handlers) {
614
+ elementItem.removeEventListener(eventName, handler.callback, {
615
+ capture: handler["option"]["capture"],
616
+ });
617
+ }
618
+ const events = Reflect.get(elementItem, symbolEvents);
619
+ DOMUtilsCommonUtils.delete(events, eventName);
620
+ });
621
+ });
622
+ });
623
+ }
638
624
 
639
- /**
640
- * 等待文档加载完成后执行指定的函数
641
- * @param callback 需要执行的函数
642
- * @example
643
- * DOMUtils.ready(function(){
644
- * console.log("文档加载完毕")
645
- * })
646
- */
647
- ready<T extends Function>(callback: T) {
648
- if (typeof callback !== "function") {
649
- return;
650
- }
651
- let DOMUtilsContext = this;
652
- /**
653
- * 检测文档是否加载完毕
654
- */
655
- function checkDOMReadyState() {
656
- try {
657
- if (
658
- DOMUtilsContext.windowApi.document.readyState === "complete" ||
659
- (DOMUtilsContext.windowApi.document.readyState !== "loading" &&
660
- !(DOMUtilsContext.windowApi.document.documentElement as any).doScroll)
661
- ) {
662
- return true;
663
- } else {
664
- return false;
665
- }
666
- } catch (error) {
667
- return false;
668
- }
669
- }
670
- /**
671
- * 成功加载完毕后触发的回调函数
672
- */
673
- function completed() {
674
- removeDomReadyListener();
675
- callback();
676
- }
625
+ /**
626
+ * 等待文档加载完成后执行指定的函数
627
+ * @param callback 需要执行的函数
628
+ * @example
629
+ * DOMUtils.ready(function(){
630
+ * console.log("文档加载完毕")
631
+ * })
632
+ */
633
+ ready<T extends (...args: any[]) => any>(callback: T) {
634
+ if (typeof callback !== "function") {
635
+ return;
636
+ }
637
+ const DOMUtilsContext = this;
638
+ /**
639
+ * 检测文档是否加载完毕
640
+ */
641
+ function checkDOMReadyState() {
642
+ try {
643
+ if (
644
+ DOMUtilsContext.windowApi.document.readyState === "complete" ||
645
+ (DOMUtilsContext.windowApi.document.readyState !== "loading" &&
646
+ !(DOMUtilsContext.windowApi.document.documentElement as any).doScroll)
647
+ ) {
648
+ return true;
649
+ } else {
650
+ return false;
651
+ }
652
+ } catch {
653
+ return false;
654
+ }
655
+ }
656
+ /**
657
+ * 成功加载完毕后触发的回调函数
658
+ */
659
+ function completed() {
660
+ removeDomReadyListener();
661
+ callback();
662
+ }
677
663
 
678
- let targetList = [
679
- {
680
- target: DOMUtilsContext.windowApi.document,
681
- eventType: "DOMContentLoaded",
682
- callback: completed,
683
- },
684
- {
685
- target: DOMUtilsContext.windowApi.window,
686
- eventType: "load",
687
- callback: completed,
688
- },
689
- ];
690
- /**
691
- * 添加监听
692
- */
693
- function addDomReadyListener() {
694
- for (let index = 0; index < targetList.length; index++) {
695
- let item = targetList[index];
696
- item.target.addEventListener(item.eventType, item.callback);
697
- }
698
- }
699
- /**
700
- * 移除监听
701
- */
702
- function removeDomReadyListener() {
703
- for (let index = 0; index < targetList.length; index++) {
704
- let item = targetList[index];
705
- item.target.removeEventListener(item.eventType, item.callback);
706
- }
707
- }
708
- if (checkDOMReadyState()) {
709
- /* 检查document状态 */
710
- DOMUtilsCommonUtils.setTimeout(callback);
711
- } else {
712
- /* 添加监听 */
713
- addDomReadyListener();
714
- }
715
- }
716
- /**
717
- * 主动触发事件
718
- * @param element 需要触发的元素|元素数组|window
719
- * @param eventType 需要触发的事件
720
- * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
721
- * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
722
- * @example
723
- * // 触发元素a.xx的click事件
724
- * DOMUtils.trigger(document.querySelector("a.xx"),"click")
725
- * DOMUtils.trigger("a.xx","click")
726
- * // 触发元素a.xx的click、tap、hover事件
727
- * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
728
- * DOMUtils.trigger("a.xx",["click","tap","hover"])
729
- */
730
- trigger(
731
- element:
732
- | DOMUtilsTargetElementType
733
- | Element
734
- | DocumentFragment
735
- | any[]
736
- | typeof globalThis
737
- | Window
738
- | Document,
739
- eventType: string,
740
- details?: object,
741
- useDispatchToTriggerEvent?: boolean
742
- ): void;
743
- /**
744
- * 主动触发事件
745
- * @param element 需要触发的元素|元素数组|window
746
- * @param eventType 需要触发的事件
747
- * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
748
- * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
749
- * @example
750
- * // 触发元素a.xx的click事件
751
- * DOMUtils.trigger(document.querySelector("a.xx"),"click")
752
- * DOMUtils.trigger("a.xx","click")
753
- * // 触发元素a.xx的click、tap、hover事件
754
- * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
755
- * DOMUtils.trigger("a.xx",["click","tap","hover"])
756
- */
757
- trigger(
758
- element: HTMLElement | string | NodeList | any[] | Window | Document,
759
- eventType: DOMUtils_EventType | DOMUtils_EventType[],
760
- details?: object,
761
- useDispatchToTriggerEvent?: boolean
762
- ): void;
763
- /**
764
- * 主动触发事件
765
- * @param element 需要触发的元素|元素数组|window
766
- * @param eventType 需要触发的事件
767
- * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
768
- * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
769
- * @example
770
- * // 触发元素a.xx的click事件
771
- * DOMUtils.trigger(document.querySelector("a.xx"),"click")
772
- * DOMUtils.trigger("a.xx","click")
773
- * // 触发元素a.xx的click、tap、hover事件
774
- * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
775
- * DOMUtils.trigger("a.xx",["click","tap","hover"])
776
- */
777
- trigger(
778
- element: HTMLElement | string | NodeList | any[] | Window | Document,
779
- eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
780
- details?: object,
781
- useDispatchToTriggerEvent: boolean = true
782
- ) {
783
- let DOMUtilsContext = this;
784
- if (typeof element === "string") {
785
- element = DOMUtilsContext.selectorAll(element);
786
- }
787
- if (element == null) {
788
- return;
789
- }
790
- let elementList = [];
791
- if (element instanceof NodeList || Array.isArray(element)) {
792
- element = element as HTMLElement[];
793
- elementList = [...element];
794
- } else {
795
- elementList = [element];
796
- }
797
- let eventTypeList: string[] = [];
798
- if (Array.isArray(eventType)) {
799
- eventTypeList = eventType as string[];
800
- } else if (typeof eventType === "string") {
801
- eventTypeList = eventType.split(" ");
802
- }
664
+ const targetList = [
665
+ {
666
+ target: DOMUtilsContext.windowApi.document,
667
+ eventType: "DOMContentLoaded",
668
+ callback: completed,
669
+ },
670
+ {
671
+ target: DOMUtilsContext.windowApi.window,
672
+ eventType: "load",
673
+ callback: completed,
674
+ },
675
+ ];
676
+ /**
677
+ * 添加监听
678
+ */
679
+ function addDomReadyListener() {
680
+ for (let index = 0; index < targetList.length; index++) {
681
+ const item = targetList[index];
682
+ item.target.addEventListener(item.eventType, item.callback);
683
+ }
684
+ }
685
+ /**
686
+ * 移除监听
687
+ */
688
+ function removeDomReadyListener() {
689
+ for (let index = 0; index < targetList.length; index++) {
690
+ const item = targetList[index];
691
+ item.target.removeEventListener(item.eventType, item.callback);
692
+ }
693
+ }
694
+ if (checkDOMReadyState()) {
695
+ /* 检查document状态 */
696
+ DOMUtilsCommonUtils.setTimeout(callback);
697
+ } else {
698
+ /* 添加监听 */
699
+ addDomReadyListener();
700
+ }
701
+ }
702
+ /**
703
+ * 主动触发事件
704
+ * @param element 需要触发的元素|元素数组|window
705
+ * @param eventType 需要触发的事件
706
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
707
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
708
+ * @example
709
+ * // 触发元素a.xx的click事件
710
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
711
+ * DOMUtils.trigger("a.xx","click")
712
+ * // 触发元素a.xx的click、tap、hover事件
713
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
714
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
715
+ */
716
+ trigger(
717
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | any[] | typeof globalThis | Window | Document,
718
+ eventType: string,
719
+ details?: object,
720
+ useDispatchToTriggerEvent?: boolean
721
+ ): void;
722
+ /**
723
+ * 主动触发事件
724
+ * @param element 需要触发的元素|元素数组|window
725
+ * @param eventType 需要触发的事件
726
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
727
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
728
+ * @example
729
+ * // 触发元素a.xx的click事件
730
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
731
+ * DOMUtils.trigger("a.xx","click")
732
+ * // 触发元素a.xx的click、tap、hover事件
733
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
734
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
735
+ */
736
+ trigger(
737
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
738
+ eventType: DOMUtils_EventType | DOMUtils_EventType[],
739
+ details?: object,
740
+ useDispatchToTriggerEvent?: boolean
741
+ ): void;
742
+ /**
743
+ * 主动触发事件
744
+ * @param element 需要触发的元素|元素数组|window
745
+ * @param eventType 需要触发的事件
746
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
747
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
748
+ * @example
749
+ * // 触发元素a.xx的click事件
750
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
751
+ * DOMUtils.trigger("a.xx","click")
752
+ * // 触发元素a.xx的click、tap、hover事件
753
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
754
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
755
+ */
756
+ trigger(
757
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
758
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
759
+ details?: object,
760
+ useDispatchToTriggerEvent: boolean = true
761
+ ) {
762
+ const DOMUtilsContext = this;
763
+ if (typeof element === "string") {
764
+ element = DOMUtilsContext.selectorAll(element);
765
+ }
766
+ if (element == null) {
767
+ return;
768
+ }
769
+ let elementList = [];
770
+ if (element instanceof NodeList || Array.isArray(element)) {
771
+ element = element as HTMLElement[];
772
+ elementList = [...element];
773
+ } else {
774
+ elementList = [element];
775
+ }
776
+ let eventTypeList: string[] = [];
777
+ if (Array.isArray(eventType)) {
778
+ eventTypeList = eventType as string[];
779
+ } else if (typeof eventType === "string") {
780
+ eventTypeList = eventType.split(" ");
781
+ }
803
782
 
804
- elementList.forEach((elementItem) => {
805
- /* 获取对象上的事件 */
806
- let events = elementItem[DOMUtilsData.SymbolEvents] || {};
807
- eventTypeList.forEach((_eventType_) => {
808
- let event: Event = null as any;
809
- if (details && details instanceof Event) {
810
- event = details;
811
- } else {
812
- event = new Event(_eventType_);
813
- if (details) {
814
- Object.keys(details).forEach((keyName) => {
815
- (event as any)[keyName] = (details as any)[keyName];
816
- });
817
- }
818
- }
819
- if (useDispatchToTriggerEvent == false && _eventType_ in events) {
820
- events[_eventType_].forEach((eventsItem: any) => {
821
- eventsItem.callback(event);
822
- });
823
- } else {
824
- elementItem.dispatchEvent(event);
825
- }
826
- });
827
- });
828
- }
783
+ elementList.forEach((elementItem) => {
784
+ /* 获取对象上的事件 */
785
+ const events = elementItem[DOMUtilsData.SymbolEvents] || {};
786
+ eventTypeList.forEach((_eventType_) => {
787
+ let event: Event = null as any;
788
+ if (details && details instanceof Event) {
789
+ event = details;
790
+ } else {
791
+ event = new Event(_eventType_);
792
+ if (details) {
793
+ Object.keys(details).forEach((keyName) => {
794
+ (event as any)[keyName] = (details as any)[keyName];
795
+ });
796
+ }
797
+ }
798
+ if (useDispatchToTriggerEvent == false && _eventType_ in events) {
799
+ events[_eventType_].forEach((eventsItem: any) => {
800
+ eventsItem.callback(event);
801
+ });
802
+ } else {
803
+ elementItem.dispatchEvent(event);
804
+ }
805
+ });
806
+ });
807
+ }
829
808
 
830
- /**
831
- * 绑定或触发元素的click事件
832
- * @param element 目标元素
833
- * @param handler (可选)事件处理函数
834
- * @param details (可选)赋予触发的Event的额外属性
835
- * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
836
- * @example
837
- * // 触发元素a.xx的click事件
838
- * DOMUtils.click(document.querySelector("a.xx"))
839
- * DOMUtils.click("a.xx")
840
- * DOMUtils.click("a.xx",function(){
841
- * console.log("触发click事件成功")
842
- * })
843
- * */
844
- click(
845
- element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
846
- handler?: (this: HTMLElement, event: DOMUtils_Event["click"]) => void,
847
- details?: any,
848
- useDispatchToTriggerEvent?: boolean
849
- ) {
850
- let DOMUtilsContext = this;
851
- if (typeof element === "string") {
852
- element = DOMUtilsContext.selectorAll(element);
853
- }
854
- if (element == null) {
855
- return;
856
- }
857
- if (DOMUtilsCommonUtils.isNodeList(element)) {
858
- // 设置
859
- element.forEach(($ele) => {
860
- DOMUtilsContext.click($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
861
- });
862
- return;
863
- }
864
- if (handler == null) {
865
- DOMUtilsContext.trigger(element, "click", details, useDispatchToTriggerEvent);
866
- } else {
867
- DOMUtilsContext.on(element, "click", null, handler);
868
- }
869
- }
870
- /**
871
- * 绑定或触发元素的blur事件
872
- * @param element 目标元素
873
- * @param handler (可选)事件处理函数
874
- * @param details (可选)赋予触发的Event的额外属性
875
- * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
876
- * @example
877
- * // 触发元素a.xx的blur事件
878
- * DOMUtils.blur(document.querySelector("a.xx"))
879
- * DOMUtils.blur("a.xx")
880
- * DOMUtils.blur("a.xx",function(){
881
- * console.log("触发blur事件成功")
882
- * })
883
- * */
884
- blur(
885
- element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
886
- handler?: (this: HTMLElement, event: DOMUtils_Event["blur"]) => void,
887
- details?: object,
888
- useDispatchToTriggerEvent?: boolean
889
- ) {
890
- let DOMUtilsContext = this;
891
- if (typeof element === "string") {
892
- element = DOMUtilsContext.selectorAll(element);
893
- }
894
- if (element == null) {
895
- return;
896
- }
897
- if (DOMUtilsCommonUtils.isNodeList(element)) {
898
- // 设置
899
- element.forEach(($ele) => {
900
- DOMUtilsContext.focus($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
901
- });
902
- return;
903
- }
904
- if (handler === null) {
905
- DOMUtilsContext.trigger(element, "blur", details, useDispatchToTriggerEvent);
906
- } else {
907
- DOMUtilsContext.on(element, "blur", null, handler as (event: Event) => void);
908
- }
909
- }
910
- /**
911
- * 绑定或触发元素的focus事件
912
- * @param element 目标元素
913
- * @param handler (可选)事件处理函数
914
- * @param details (可选)赋予触发的Event的额外属性
915
- * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
916
- * @example
917
- * // 触发元素a.xx的focus事件
918
- * DOMUtils.focus(document.querySelector("a.xx"))
919
- * DOMUtils.focus("a.xx")
920
- * DOMUtils.focus("a.xx",function(){
921
- * console.log("触发focus事件成功")
922
- * })
923
- * */
924
- focus(
925
- element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
926
- handler?: (this: HTMLElement, event: DOMUtils_Event["focus"]) => void,
927
- details?: object,
928
- useDispatchToTriggerEvent?: boolean
929
- ) {
930
- let DOMUtilsContext = this;
931
- if (typeof element === "string") {
932
- element = DOMUtilsContext.selectorAll(element);
933
- }
934
- if (element == null) {
935
- return;
936
- }
937
- if (DOMUtilsCommonUtils.isNodeList(element)) {
938
- // 设置
939
- element.forEach(($ele) => {
940
- DOMUtilsContext.focus($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
941
- });
942
- return;
943
- }
944
- if (handler == null) {
945
- DOMUtilsContext.trigger(element, "focus", details, useDispatchToTriggerEvent);
946
- } else {
947
- DOMUtilsContext.on(element, "focus", null, handler);
948
- }
949
- }
950
- /**
951
- * 当鼠标移入或移出元素时触发事件
952
- * @param element 当前元素
953
- * @param handler 事件处理函数
954
- * @param option 配置
955
- * @example
956
- * // 监听a.xx元素的移入或移出
957
- * DOMUtils.hover(document.querySelector("a.xx"),()=>{
958
- * console.log("移入/移除");
959
- * })
960
- * DOMUtils.hover("a.xx",()=>{
961
- * console.log("移入/移除");
962
- * })
963
- */
964
- hover(
965
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Node,
966
- handler: (this: HTMLElement, event: DOMUtils_Event["hover"]) => void,
967
- option?: boolean | DOMUtilsEventListenerOption
968
- ) {
969
- let DOMUtilsContext = this;
970
- if (typeof element === "string") {
971
- element = DOMUtilsContext.selectorAll(element);
972
- }
973
- if (element == null) {
974
- return;
975
- }
976
- if (DOMUtilsCommonUtils.isNodeList(element)) {
977
- // 设置
978
- element.forEach(($ele) => {
979
- DOMUtilsContext.hover($ele as HTMLElement, handler, option);
980
- });
981
- return;
982
- }
983
- DOMUtilsContext.on(element, "mouseenter", null, handler, option);
984
- DOMUtilsContext.on(element, "mouseleave", null, handler, option);
985
- }
986
- /**
987
- * 当动画结束时触发事件
988
- * @param element 监听的元素
989
- * @param handler 触发的回调函数
990
- * @param option 配置项,这里默认配置once为true
991
- */
992
- animationend(
993
- element: HTMLElement | string | Element | DocumentFragment,
994
- handler: (this: HTMLElement, event: DOMUtils_Event["animationend"]) => void,
995
- option?: boolean | DOMUtilsEventListenerOption
996
- ) {
997
- let DOMUtilsContext = this;
998
- if (typeof element === "string") {
999
- element = DOMUtilsContext.selector(element)!;
1000
- }
1001
- if (element == null) {
1002
- return;
1003
- }
1004
- // if (DOMUtilsCommonUtils.isNodeList(element)) {
1005
- // // 设置
1006
- // element.forEach(($ele) => {
1007
- // DOMUtilsContext.animationend($ele as HTMLElement, handler, option);
1008
- // });
1009
- // return;
1010
- // }
1011
- const defaultOption: DOMUtilsEventListenerOption = {
1012
- once: true,
1013
- };
1014
- Object.assign(defaultOption, option || {});
1015
- const eventNameList = DOMUtilsCommonUtils.getAnimationEndNameList();
1016
- DOMUtilsContext.on(element, eventNameList, null, handler, defaultOption);
1017
- if (!defaultOption.once) {
1018
- return {
1019
- off() {
1020
- DOMUtilsContext.off(element, eventNameList, null, handler, defaultOption);
1021
- },
1022
- };
1023
- }
1024
- }
1025
- /**
1026
- * 当过渡结束时触发事件
1027
- * @param element 监听的元素
1028
- * @param handler 触发的回调函数
1029
- * @param option 配置项,这里默认配置once为true
1030
- */
1031
- transitionend(
1032
- element: HTMLElement | string | Element | DocumentFragment,
1033
- handler: (this: HTMLElement, event: DOMUtils_Event["transitionend"]) => void,
1034
- option?: boolean | DOMUtilsEventListenerOption
1035
- ) {
1036
- let DOMUtilsContext = this;
1037
- if (typeof element === "string") {
1038
- element = DOMUtilsContext.selector(element)!;
1039
- }
1040
- if (element == null) {
1041
- return;
1042
- }
1043
- // if (DOMUtilsCommonUtils.isNodeList(element)) {
1044
- // // 设置
1045
- // element.forEach(($ele) => {
1046
- // DOMUtilsContext.transitionend($ele as HTMLElement, handler, option);
1047
- // });
1048
- // return;
1049
- // }
1050
- const defaultOption: DOMUtilsEventListenerOption = {
1051
- once: true,
1052
- };
1053
- Object.assign(defaultOption, option || {});
1054
- const eventNameList = DOMUtilsCommonUtils.getTransitionEndNameList();
1055
- DOMUtilsContext.on(element, eventNameList, null, handler, defaultOption);
1056
- if (!defaultOption.once) {
1057
- return {
1058
- off() {
1059
- DOMUtilsContext.off(element, eventNameList, null, handler, defaultOption);
1060
- },
1061
- };
1062
- }
1063
- }
1064
- /**
1065
- * 当按键松开时触发事件
1066
- * keydown - > keypress - > keyup
1067
- * @param element 当前元素
1068
- * @param handler 事件处理函数
1069
- * @param option 配置
1070
- * @example
1071
- * // 监听a.xx元素的按键松开
1072
- * DOMUtils.keyup(document.querySelector("a.xx"),()=>{
1073
- * console.log("按键松开");
1074
- * })
1075
- * DOMUtils.keyup("a.xx",()=>{
1076
- * console.log("按键松开");
1077
- * })
1078
- */
1079
- keyup(
1080
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1081
- handler: (this: HTMLElement, event: DOMUtils_Event["keyup"]) => void,
1082
- option?: boolean | DOMUtilsEventListenerOption
1083
- ) {
1084
- let DOMUtilsContext = this;
1085
- if (element == null) {
1086
- return;
1087
- }
1088
- if (typeof element === "string") {
1089
- element = DOMUtilsContext.selectorAll(element);
1090
- }
1091
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1092
- // 设置
1093
- element.forEach(($ele) => {
1094
- DOMUtilsContext.keyup($ele as HTMLElement, handler, option);
1095
- });
1096
- return;
1097
- }
1098
- DOMUtilsContext.on(element, "keyup", null, handler, option);
1099
- }
1100
- /**
1101
- * 当按键按下时触发事件
1102
- * keydown - > keypress - > keyup
1103
- * @param element 目标
1104
- * @param handler 事件处理函数
1105
- * @param option 配置
1106
- * @example
1107
- * // 监听a.xx元素的按键按下
1108
- * DOMUtils.keydown(document.querySelector("a.xx"),()=>{
1109
- * console.log("按键按下");
1110
- * })
1111
- * DOMUtils.keydown("a.xx",()=>{
1112
- * console.log("按键按下");
1113
- * })
1114
- */
1115
- keydown(
1116
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1117
- handler: (this: HTMLElement, event: DOMUtils_Event["keydown"]) => void,
1118
- option?: boolean | DOMUtilsEventListenerOption
1119
- ) {
1120
- let DOMUtilsContext = this;
1121
- if (element == null) {
1122
- return;
1123
- }
1124
- if (typeof element === "string") {
1125
- element = DOMUtilsContext.selectorAll(element);
1126
- }
1127
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1128
- // 设置
1129
- element.forEach(($ele) => {
1130
- DOMUtilsContext.keydown($ele as HTMLElement, handler, option);
1131
- });
1132
- return;
1133
- }
1134
- DOMUtilsContext.on(element, "keydown", null, handler, option);
1135
- }
1136
- /**
1137
- * 当按键按下时触发事件
1138
- * keydown - > keypress - > keyup
1139
- * @param element 目标
1140
- * @param handler 事件处理函数
1141
- * @param option 配置
1142
- * @example
1143
- * // 监听a.xx元素的按键按下
1144
- * DOMUtils.keypress(document.querySelector("a.xx"),()=>{
1145
- * console.log("按键按下");
1146
- * })
1147
- * DOMUtils.keypress("a.xx",()=>{
1148
- * console.log("按键按下");
1149
- * })
1150
- */
1151
- keypress(
1152
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1153
- handler: (this: HTMLElement, event: DOMUtils_Event["keypress"]) => void,
1154
- option?: boolean | DOMUtilsEventListenerOption
1155
- ) {
1156
- let DOMUtilsContext = this;
1157
- if (element == null) {
1158
- return;
1159
- }
1160
- if (typeof element === "string") {
1161
- element = DOMUtilsContext.selectorAll(element);
1162
- }
1163
- if (DOMUtilsCommonUtils.isNodeList(element)) {
1164
- // 设置
1165
- element.forEach(($ele) => {
1166
- DOMUtilsContext.keypress($ele as HTMLElement, handler, option);
1167
- });
1168
- return;
1169
- }
1170
- DOMUtilsContext.on(element, "keypress", null, handler, option);
1171
- }
1172
- /**
809
+ /**
810
+ * 绑定或触发元素的click事件
811
+ * @param element 目标元素
812
+ * @param handler (可选)事件处理函数
813
+ * @param details (可选)赋予触发的Event的额外属性
814
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
815
+ * @example
816
+ * // 触发元素a.xx的click事件
817
+ * DOMUtils.click(document.querySelector("a.xx"))
818
+ * DOMUtils.click("a.xx")
819
+ * DOMUtils.click("a.xx",function(){
820
+ * console.log("触发click事件成功")
821
+ * })
822
+ * */
823
+ click(
824
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
825
+ handler?: (this: HTMLElement, event: DOMUtils_Event["click"]) => void,
826
+ details?: any,
827
+ useDispatchToTriggerEvent?: boolean
828
+ ) {
829
+ const DOMUtilsContext = this;
830
+ if (typeof element === "string") {
831
+ element = DOMUtilsContext.selectorAll(element);
832
+ }
833
+ if (element == null) {
834
+ return;
835
+ }
836
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
837
+ // 设置
838
+ element.forEach(($ele) => {
839
+ DOMUtilsContext.click($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
840
+ });
841
+ return;
842
+ }
843
+ if (handler == null) {
844
+ DOMUtilsContext.trigger(element, "click", details, useDispatchToTriggerEvent);
845
+ } else {
846
+ DOMUtilsContext.on(element, "click", null, handler);
847
+ }
848
+ }
849
+ /**
850
+ * 绑定或触发元素的blur事件
851
+ * @param element 目标元素
852
+ * @param handler (可选)事件处理函数
853
+ * @param details (可选)赋予触发的Event的额外属性
854
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
855
+ * @example
856
+ * // 触发元素a.xx的blur事件
857
+ * DOMUtils.blur(document.querySelector("a.xx"))
858
+ * DOMUtils.blur("a.xx")
859
+ * DOMUtils.blur("a.xx",function(){
860
+ * console.log("触发blur事件成功")
861
+ * })
862
+ * */
863
+ blur(
864
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
865
+ handler?: (this: HTMLElement, event: DOMUtils_Event["blur"]) => void,
866
+ details?: object,
867
+ useDispatchToTriggerEvent?: boolean
868
+ ) {
869
+ const DOMUtilsContext = this;
870
+ if (typeof element === "string") {
871
+ element = DOMUtilsContext.selectorAll(element);
872
+ }
873
+ if (element == null) {
874
+ return;
875
+ }
876
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
877
+ // 设置
878
+ element.forEach(($ele) => {
879
+ DOMUtilsContext.focus($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
880
+ });
881
+ return;
882
+ }
883
+ if (handler === null) {
884
+ DOMUtilsContext.trigger(element, "blur", details, useDispatchToTriggerEvent);
885
+ } else {
886
+ DOMUtilsContext.on(element, "blur", null, handler as (event: Event) => void);
887
+ }
888
+ }
889
+ /**
890
+ * 绑定或触发元素的focus事件
891
+ * @param element 目标元素
892
+ * @param handler (可选)事件处理函数
893
+ * @param details (可选)赋予触发的Event的额外属性
894
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
895
+ * @example
896
+ * // 触发元素a.xx的focus事件
897
+ * DOMUtils.focus(document.querySelector("a.xx"))
898
+ * DOMUtils.focus("a.xx")
899
+ * DOMUtils.focus("a.xx",function(){
900
+ * console.log("触发focus事件成功")
901
+ * })
902
+ * */
903
+ focus(
904
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
905
+ handler?: (this: HTMLElement, event: DOMUtils_Event["focus"]) => void,
906
+ details?: object,
907
+ useDispatchToTriggerEvent?: boolean
908
+ ) {
909
+ const DOMUtilsContext = this;
910
+ if (typeof element === "string") {
911
+ element = DOMUtilsContext.selectorAll(element);
912
+ }
913
+ if (element == null) {
914
+ return;
915
+ }
916
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
917
+ // 设置
918
+ element.forEach(($ele) => {
919
+ DOMUtilsContext.focus($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
920
+ });
921
+ return;
922
+ }
923
+ if (handler == null) {
924
+ DOMUtilsContext.trigger(element, "focus", details, useDispatchToTriggerEvent);
925
+ } else {
926
+ DOMUtilsContext.on(element, "focus", null, handler);
927
+ }
928
+ }
929
+ /**
930
+ * 当鼠标移入或移出元素时触发事件
931
+ * @param element 当前元素
932
+ * @param handler 事件处理函数
933
+ * @param option 配置
934
+ * @example
935
+ * // 监听a.xx元素的移入或移出
936
+ * DOMUtils.hover(document.querySelector("a.xx"),()=>{
937
+ * console.log("移入/移除");
938
+ * })
939
+ * DOMUtils.hover("a.xx",()=>{
940
+ * console.log("移入/移除");
941
+ * })
942
+ */
943
+ hover(
944
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Node,
945
+ handler: (this: HTMLElement, event: DOMUtils_Event["hover"]) => void,
946
+ option?: boolean | DOMUtilsEventListenerOption
947
+ ) {
948
+ const DOMUtilsContext = this;
949
+ if (typeof element === "string") {
950
+ element = DOMUtilsContext.selectorAll(element);
951
+ }
952
+ if (element == null) {
953
+ return;
954
+ }
955
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
956
+ // 设置
957
+ element.forEach(($ele) => {
958
+ DOMUtilsContext.hover($ele as HTMLElement, handler, option);
959
+ });
960
+ return;
961
+ }
962
+ DOMUtilsContext.on(element, "mouseenter", null, handler, option);
963
+ DOMUtilsContext.on(element, "mouseleave", null, handler, option);
964
+ }
965
+ /**
966
+ * 当动画结束时触发事件
967
+ * @param element 监听的元素
968
+ * @param handler 触发的回调函数
969
+ * @param option 配置项,这里默认配置once为true
970
+ */
971
+ animationend(
972
+ element: HTMLElement | string | Element | DocumentFragment,
973
+ handler: (this: HTMLElement, event: DOMUtils_Event["animationend"]) => void,
974
+ option?: boolean | DOMUtilsEventListenerOption
975
+ ) {
976
+ const DOMUtilsContext = this;
977
+ if (typeof element === "string") {
978
+ element = DOMUtilsContext.selector(element)!;
979
+ }
980
+ if (element == null) {
981
+ return;
982
+ }
983
+ // if (DOMUtilsCommonUtils.isNodeList(element)) {
984
+ // // 设置
985
+ // element.forEach(($ele) => {
986
+ // DOMUtilsContext.animationend($ele as HTMLElement, handler, option);
987
+ // });
988
+ // return;
989
+ // }
990
+ const defaultOption: DOMUtilsEventListenerOption = {
991
+ once: true,
992
+ };
993
+ Object.assign(defaultOption, option || {});
994
+ const eventNameList = DOMUtilsCommonUtils.getAnimationEndNameList();
995
+ DOMUtilsContext.on(element, eventNameList, null, handler, defaultOption);
996
+ if (!defaultOption.once) {
997
+ return {
998
+ off() {
999
+ DOMUtilsContext.off(element, eventNameList, null, handler, defaultOption);
1000
+ },
1001
+ };
1002
+ }
1003
+ }
1004
+ /**
1005
+ * 当过渡结束时触发事件
1006
+ * @param element 监听的元素
1007
+ * @param handler 触发的回调函数
1008
+ * @param option 配置项,这里默认配置once为true
1009
+ */
1010
+ transitionend(
1011
+ element: HTMLElement | string | Element | DocumentFragment,
1012
+ handler: (this: HTMLElement, event: DOMUtils_Event["transitionend"]) => void,
1013
+ option?: boolean | DOMUtilsEventListenerOption
1014
+ ) {
1015
+ const DOMUtilsContext = this;
1016
+ if (typeof element === "string") {
1017
+ element = DOMUtilsContext.selector(element)!;
1018
+ }
1019
+ if (element == null) {
1020
+ return;
1021
+ }
1022
+ // if (DOMUtilsCommonUtils.isNodeList(element)) {
1023
+ // // 设置
1024
+ // element.forEach(($ele) => {
1025
+ // DOMUtilsContext.transitionend($ele as HTMLElement, handler, option);
1026
+ // });
1027
+ // return;
1028
+ // }
1029
+ const defaultOption: DOMUtilsEventListenerOption = {
1030
+ once: true,
1031
+ };
1032
+ Object.assign(defaultOption, option || {});
1033
+ const eventNameList = DOMUtilsCommonUtils.getTransitionEndNameList();
1034
+ DOMUtilsContext.on(element, eventNameList, null, handler, defaultOption);
1035
+ if (!defaultOption.once) {
1036
+ return {
1037
+ off() {
1038
+ DOMUtilsContext.off(element, eventNameList, null, handler, defaultOption);
1039
+ },
1040
+ };
1041
+ }
1042
+ }
1043
+ /**
1044
+ * 当按键松开时触发事件
1045
+ * keydown - > keypress - > keyup
1046
+ * @param element 当前元素
1047
+ * @param handler 事件处理函数
1048
+ * @param option 配置
1049
+ * @example
1050
+ * // 监听a.xx元素的按键松开
1051
+ * DOMUtils.keyup(document.querySelector("a.xx"),()=>{
1052
+ * console.log("按键松开");
1053
+ * })
1054
+ * DOMUtils.keyup("a.xx",()=>{
1055
+ * console.log("按键松开");
1056
+ * })
1057
+ */
1058
+ keyup(
1059
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1060
+ handler: (this: HTMLElement, event: DOMUtils_Event["keyup"]) => void,
1061
+ option?: boolean | DOMUtilsEventListenerOption
1062
+ ) {
1063
+ const DOMUtilsContext = this;
1064
+ if (element == null) {
1065
+ return;
1066
+ }
1067
+ if (typeof element === "string") {
1068
+ element = DOMUtilsContext.selectorAll(element);
1069
+ }
1070
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1071
+ // 设置
1072
+ element.forEach(($ele) => {
1073
+ DOMUtilsContext.keyup($ele as HTMLElement, handler, option);
1074
+ });
1075
+ return;
1076
+ }
1077
+ DOMUtilsContext.on(element, "keyup", null, handler, option);
1078
+ }
1079
+ /**
1080
+ * 当按键按下时触发事件
1081
+ * keydown - > keypress - > keyup
1082
+ * @param element 目标
1083
+ * @param handler 事件处理函数
1084
+ * @param option 配置
1085
+ * @example
1086
+ * // 监听a.xx元素的按键按下
1087
+ * DOMUtils.keydown(document.querySelector("a.xx"),()=>{
1088
+ * console.log("按键按下");
1089
+ * })
1090
+ * DOMUtils.keydown("a.xx",()=>{
1091
+ * console.log("按键按下");
1092
+ * })
1093
+ */
1094
+ keydown(
1095
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1096
+ handler: (this: HTMLElement, event: DOMUtils_Event["keydown"]) => void,
1097
+ option?: boolean | DOMUtilsEventListenerOption
1098
+ ) {
1099
+ const DOMUtilsContext = this;
1100
+ if (element == null) {
1101
+ return;
1102
+ }
1103
+ if (typeof element === "string") {
1104
+ element = DOMUtilsContext.selectorAll(element);
1105
+ }
1106
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1107
+ // 设置
1108
+ element.forEach(($ele) => {
1109
+ DOMUtilsContext.keydown($ele as HTMLElement, handler, option);
1110
+ });
1111
+ return;
1112
+ }
1113
+ DOMUtilsContext.on(element, "keydown", null, handler, option);
1114
+ }
1115
+ /**
1116
+ * 当按键按下时触发事件
1117
+ * keydown - > keypress - > keyup
1118
+ * @param element 目标
1119
+ * @param handler 事件处理函数
1120
+ * @param option 配置
1121
+ * @example
1122
+ * // 监听a.xx元素的按键按下
1123
+ * DOMUtils.keypress(document.querySelector("a.xx"),()=>{
1124
+ * console.log("按键按下");
1125
+ * })
1126
+ * DOMUtils.keypress("a.xx",()=>{
1127
+ * console.log("按键按下");
1128
+ * })
1129
+ */
1130
+ keypress(
1131
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1132
+ handler: (this: HTMLElement, event: DOMUtils_Event["keypress"]) => void,
1133
+ option?: boolean | DOMUtilsEventListenerOption
1134
+ ) {
1135
+ const DOMUtilsContext = this;
1136
+ if (element == null) {
1137
+ return;
1138
+ }
1139
+ if (typeof element === "string") {
1140
+ element = DOMUtilsContext.selectorAll(element);
1141
+ }
1142
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1143
+ // 设置
1144
+ element.forEach(($ele) => {
1145
+ DOMUtilsContext.keypress($ele as HTMLElement, handler, option);
1146
+ });
1147
+ return;
1148
+ }
1149
+ DOMUtilsContext.on(element, "keypress", null, handler, option);
1150
+ }
1151
+ /**
1173
1152
  * 监听某个元素键盘按键事件或window全局按键事件
1174
1153
  * 按下有值的键时触发,按下Ctrl\Alt\Shift\Meta是无值键。按下先触发keydown事件,再触发keypress事件。
1175
1154
  * @param element 需要监听的对象,可以是全局Window或者某个元素
@@ -1232,311 +1211,293 @@ export class DOMUtilsEvent {
1232
1211
  搜索 170
1233
1212
  收藏 171
1234
1213
  **/
1235
- listenKeyboard(
1236
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1237
- eventName: "keyup" | "keypress" | "keydown" = "keypress",
1238
- callback: (keyName: string, keyValue: number, otherCodeList: string[], event: KeyboardEvent) => void,
1239
- options?: DOMUtilsEventListenerOption | boolean
1240
- ): {
1241
- removeListen(): void;
1242
- } {
1243
- let DOMUtilsContext = this;
1244
- if (typeof element === "string") {
1245
- element = DOMUtilsContext.selectorAll(element);
1246
- }
1247
- let keyboardEventCallBack = function (event: KeyboardEvent) {
1248
- /** 键名 */
1249
- let keyName = event.key || event.code;
1250
- /** 键值 */
1251
- let keyValue = event.charCode || event.keyCode || event.which;
1252
- /** 组合键列表 */
1253
- let otherCodeList: string[] = [];
1254
- if (event.ctrlKey) {
1255
- otherCodeList.push("ctrl");
1256
- }
1257
- if (event.altKey) {
1258
- otherCodeList.push("alt");
1259
- }
1260
- if (event.metaKey) {
1261
- otherCodeList.push("meta");
1262
- }
1263
- if (event.shiftKey) {
1264
- otherCodeList.push("shift");
1265
- }
1266
- if (typeof callback === "function") {
1267
- callback(keyName, keyValue, otherCodeList, event);
1268
- }
1269
- };
1270
- DOMUtilsContext.on(element, eventName, keyboardEventCallBack, options);
1271
- return {
1272
- removeListen: () => {
1273
- DOMUtilsContext.off(element, eventName, keyboardEventCallBack, options);
1274
- },
1275
- };
1276
- }
1277
- /**
1278
- * 选择器,可使用以下的额外语法
1279
- *
1280
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1281
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1282
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1283
- * @param selector 选择器
1284
- * @param parent 指定父元素
1285
- * @example
1286
- * DOMUtils.selector("div:contains('测试')")
1287
- * > div.xxx
1288
- * @example
1289
- * DOMUtils.selector("div:empty")
1290
- * > div.xxx
1291
- * @example
1292
- * DOMUtils.selector("div:regexp('^xxxx$')")
1293
- * > div.xxx
1294
- */
1295
- selector<K extends keyof HTMLElementTagNameMap>(
1296
- selector: K,
1297
- parent?: Element | Document | DocumentFragment | ShadowRoot
1298
- ): HTMLElementTagNameMap[K] | undefined;
1299
- selector<E extends Element = HTMLElement>(
1300
- selector: string,
1301
- parent?: Element | Document | DocumentFragment | ShadowRoot
1302
- ): E | undefined;
1303
- selector<E extends Element = HTMLElement>(
1304
- selector: string,
1305
- parent?: Element | Document | DocumentFragment | ShadowRoot
1306
- ) {
1307
- return this.selectorAll<E>(selector, parent)[0];
1308
- }
1309
- /**
1310
- * 选择器,可使用以下的额外语法
1311
- *
1312
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1313
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1314
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1315
- * @param selector 选择器
1316
- * @param parent 指定父元素
1317
- * @example
1318
- * DOMUtils.selectorAll("div:contains('测试')")
1319
- * > [div.xxx]
1320
- * @example
1321
- * DOMUtils.selectorAll("div:empty")
1322
- * > [div.xxx]
1323
- * @example
1324
- * DOMUtils.selectorAll("div:regexp('^xxxx$')")
1325
- * > [div.xxx]
1326
- * @example
1327
- * DOMUtils.selectorAll("div:regexp(/^xxx/ig)")
1328
- * > [div.xxx]
1329
- */
1330
- selectorAll<K extends keyof HTMLElementTagNameMap>(
1331
- selector: K,
1332
- parent?: Element | Document | DocumentFragment | ShadowRoot
1333
- ): HTMLElementTagNameMap[K][];
1334
- selectorAll<E extends Element = HTMLElement>(
1335
- selector: string,
1336
- parent?: Element | Document | DocumentFragment | ShadowRoot
1337
- ): E[];
1338
- selectorAll<E extends Element = HTMLElement>(
1339
- selector: string,
1340
- parent?: Element | Document | DocumentFragment | ShadowRoot
1341
- ) {
1342
- const context = this;
1343
- parent = parent || context.windowApi.document;
1344
- selector = selector.trim();
1345
- if (selector.match(/[^\s]{1}:empty$/gi)) {
1346
- // empty 语法
1347
- selector = selector.replace(/:empty$/gi, "");
1348
- return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1349
- return $ele?.innerHTML?.trim() === "";
1350
- });
1351
- } else if (
1352
- selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
1353
- selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
1354
- ) {
1355
- // contains 语法
1356
- let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1357
- let text = textMatch![2];
1358
- selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1359
- return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1360
- // @ts-ignore
1361
- return ($ele?.textContent || $ele?.innerText)?.includes(text);
1362
- });
1363
- } else if (
1364
- selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
1365
- selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
1366
- ) {
1367
- // regexp 语法
1368
- let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1369
- let pattern = textMatch![2];
1370
- let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1371
- let flags = "";
1372
- if (flagMatch) {
1373
- pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1374
- flags = flagMatch[3];
1375
- }
1376
- let regexp = new RegExp(pattern, flags);
1377
- selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1378
- return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1379
- // @ts-ignore
1380
- return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
1381
- });
1382
- } else {
1383
- // 普通语法
1384
- return Array.from(parent.querySelectorAll<E>(selector));
1385
- }
1386
- }
1387
- /**
1388
- * 匹配元素,可使用以下的额外语法
1389
- *
1390
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1391
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1392
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1393
- * @param $el 元素
1394
- * @param selector 选择器
1395
- * @example
1396
- * DOMUtils.matches("div:contains('测试')")
1397
- * > true
1398
- * @example
1399
- * DOMUtils.matches("div:empty")
1400
- * > true
1401
- * @example
1402
- * DOMUtils.matches("div:regexp('^xxxx$')")
1403
- * > true
1404
- * @example
1405
- * DOMUtils.matches("div:regexp(/^xxx/ig)")
1406
- * > false
1407
- */
1408
- matches($el: HTMLElement | Element | null | undefined, selector: string): boolean {
1409
- selector = selector.trim();
1410
- if ($el == null) {
1411
- return false;
1412
- }
1214
+ listenKeyboard(
1215
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1216
+ eventName: "keyup" | "keypress" | "keydown" = "keypress",
1217
+ callback: (keyName: string, keyValue: number, otherCodeList: string[], event: KeyboardEvent) => void,
1218
+ options?: DOMUtilsEventListenerOption | boolean
1219
+ ): {
1220
+ removeListen(): void;
1221
+ } {
1222
+ const DOMUtilsContext = this;
1223
+ if (typeof element === "string") {
1224
+ element = DOMUtilsContext.selectorAll(element);
1225
+ }
1226
+ const keyboardEventCallBack = function (event: KeyboardEvent) {
1227
+ /** 键名 */
1228
+ const keyName = event.key || event.code;
1229
+ /** 键值 */
1230
+ const keyValue = event.charCode || event.keyCode || event.which;
1231
+ /** 组合键列表 */
1232
+ const otherCodeList: string[] = [];
1233
+ if (event.ctrlKey) {
1234
+ otherCodeList.push("ctrl");
1235
+ }
1236
+ if (event.altKey) {
1237
+ otherCodeList.push("alt");
1238
+ }
1239
+ if (event.metaKey) {
1240
+ otherCodeList.push("meta");
1241
+ }
1242
+ if (event.shiftKey) {
1243
+ otherCodeList.push("shift");
1244
+ }
1245
+ if (typeof callback === "function") {
1246
+ callback(keyName, keyValue, otherCodeList, event);
1247
+ }
1248
+ };
1249
+ DOMUtilsContext.on(element, eventName, keyboardEventCallBack, options);
1250
+ return {
1251
+ removeListen: () => {
1252
+ DOMUtilsContext.off(element, eventName, keyboardEventCallBack, options);
1253
+ },
1254
+ };
1255
+ }
1256
+ /**
1257
+ * 选择器,可使用以下的额外语法
1258
+ *
1259
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1260
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1261
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1262
+ * @param selector 选择器
1263
+ * @param parent 指定父元素
1264
+ * @example
1265
+ * DOMUtils.selector("div:contains('测试')")
1266
+ * > div.xxx
1267
+ * @example
1268
+ * DOMUtils.selector("div:empty")
1269
+ * > div.xxx
1270
+ * @example
1271
+ * DOMUtils.selector("div:regexp('^xxxx$')")
1272
+ * > div.xxx
1273
+ */
1274
+ selector<K extends keyof HTMLElementTagNameMap>(
1275
+ selector: K,
1276
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1277
+ ): HTMLElementTagNameMap[K] | undefined;
1278
+ selector<E extends Element = HTMLElement>(
1279
+ selector: string,
1280
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1281
+ ): E | undefined;
1282
+ selector<E extends Element = HTMLElement>(
1283
+ selector: string,
1284
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1285
+ ) {
1286
+ return this.selectorAll<E>(selector, parent)[0];
1287
+ }
1288
+ /**
1289
+ * 选择器,可使用以下的额外语法
1290
+ *
1291
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1292
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1293
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1294
+ * @param selector 选择器
1295
+ * @param parent 指定父元素
1296
+ * @example
1297
+ * DOMUtils.selectorAll("div:contains('测试')")
1298
+ * > [div.xxx]
1299
+ * @example
1300
+ * DOMUtils.selectorAll("div:empty")
1301
+ * > [div.xxx]
1302
+ * @example
1303
+ * DOMUtils.selectorAll("div:regexp('^xxxx$')")
1304
+ * > [div.xxx]
1305
+ * @example
1306
+ * DOMUtils.selectorAll("div:regexp(/^xxx/ig)")
1307
+ * > [div.xxx]
1308
+ */
1309
+ selectorAll<K extends keyof HTMLElementTagNameMap>(
1310
+ selector: K,
1311
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1312
+ ): HTMLElementTagNameMap[K][];
1313
+ selectorAll<E extends Element = HTMLElement>(
1314
+ selector: string,
1315
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1316
+ ): E[];
1317
+ selectorAll<E extends Element = HTMLElement>(
1318
+ selector: string,
1319
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1320
+ ) {
1321
+ const context = this;
1322
+ parent = parent || context.windowApi.document;
1323
+ selector = selector.trim();
1324
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1325
+ // empty 语法
1326
+ selector = selector.replace(/:empty$/gi, "");
1327
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1328
+ return $ele?.innerHTML?.trim() === "";
1329
+ });
1330
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
1331
+ // contains 语法
1332
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1333
+ const text = textMatch![2];
1334
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1335
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1336
+ // @ts-ignore
1337
+ return ($ele?.textContent || $ele?.innerText)?.includes(text);
1338
+ });
1339
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
1340
+ // regexp 语法
1341
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1342
+ let pattern = textMatch![2];
1343
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1344
+ let flags = "";
1345
+ if (flagMatch) {
1346
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1347
+ flags = flagMatch[3];
1348
+ }
1349
+ const regexp = new RegExp(pattern, flags);
1350
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1351
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1352
+ // @ts-ignore
1353
+ return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
1354
+ });
1355
+ } else {
1356
+ // 普通语法
1357
+ return Array.from(parent.querySelectorAll<E>(selector));
1358
+ }
1359
+ }
1360
+ /**
1361
+ * 匹配元素,可使用以下的额外语法
1362
+ *
1363
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1364
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1365
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1366
+ * @param $el 元素
1367
+ * @param selector 选择器
1368
+ * @example
1369
+ * DOMUtils.matches("div:contains('测试')")
1370
+ * > true
1371
+ * @example
1372
+ * DOMUtils.matches("div:empty")
1373
+ * > true
1374
+ * @example
1375
+ * DOMUtils.matches("div:regexp('^xxxx$')")
1376
+ * > true
1377
+ * @example
1378
+ * DOMUtils.matches("div:regexp(/^xxx/ig)")
1379
+ * > false
1380
+ */
1381
+ matches($el: HTMLElement | Element | null | undefined, selector: string): boolean {
1382
+ selector = selector.trim();
1383
+ if ($el == null) {
1384
+ return false;
1385
+ }
1413
1386
 
1414
- if (selector.match(/[^\s]{1}:empty$/gi)) {
1415
- // empty 语法
1416
- selector = selector.replace(/:empty$/gi, "");
1417
- return $el.matches(selector) && $el?.innerHTML?.trim() === "";
1418
- } else if (
1419
- selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
1420
- selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
1421
- ) {
1422
- // contains 语法
1423
- let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1424
- let text = textMatch![2];
1425
- selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1426
- // @ts-ignore
1427
- let content = $el?.textContent || $el?.innerText;
1428
- if (typeof content !== "string") {
1429
- content = "";
1430
- }
1431
- return $el.matches(selector) && content?.includes(text);
1432
- } else if (
1433
- selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
1434
- selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
1435
- ) {
1436
- // regexp 语法
1437
- let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1438
- let pattern = textMatch![2];
1439
- let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1440
- let flags = "";
1441
- if (flagMatch) {
1442
- pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1443
- flags = flagMatch[3];
1444
- }
1445
- let regexp = new RegExp(pattern, flags);
1446
- selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1447
- // @ts-ignore
1448
- let content = $el?.textContent || $el?.innerText;
1449
- if (typeof content !== "string") {
1450
- content = "";
1451
- }
1452
- return $el.matches(selector) && Boolean(content?.match(regexp));
1453
- } else {
1454
- // 普通语法
1455
- return $el.matches(selector);
1456
- }
1457
- }
1458
- /**
1459
- * 根据选择器获取上层元素,可使用以下的额外语法
1460
- *
1461
- * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1462
- * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1463
- * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1464
- * @param $el 元素
1465
- * @param selector 选择器
1466
- * @example
1467
- * DOMUtils.closest("div:contains('测试')")
1468
- * > div.xxx
1469
- * @example
1470
- * DOMUtils.closest("div:empty")
1471
- * > div.xxx
1472
- * @example
1473
- * DOMUtils.closest("div:regexp('^xxxx$')")
1474
- * > div.xxxx
1475
- * @example
1476
- * DOMUtils.closest("div:regexp(/^xxx/ig)")
1477
- * > null
1478
- */
1479
- closest<K extends keyof HTMLElementTagNameMap>(
1480
- $el: HTMLElement | Element,
1481
- selector: string
1482
- ): HTMLElementTagNameMap[K] | null;
1483
- closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null;
1484
- closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null {
1485
- selector = selector.trim();
1387
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1388
+ // empty 语法
1389
+ selector = selector.replace(/:empty$/gi, "");
1390
+ return $el.matches(selector) && $el?.innerHTML?.trim() === "";
1391
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
1392
+ // contains 语法
1393
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1394
+ const text = textMatch![2];
1395
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1396
+ // @ts-ignore
1397
+ let content = $el?.textContent || $el?.innerText;
1398
+ if (typeof content !== "string") {
1399
+ content = "";
1400
+ }
1401
+ return $el.matches(selector) && content?.includes(text);
1402
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
1403
+ // regexp 语法
1404
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1405
+ let pattern = textMatch![2];
1406
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1407
+ let flags = "";
1408
+ if (flagMatch) {
1409
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1410
+ flags = flagMatch[3];
1411
+ }
1412
+ const regexp = new RegExp(pattern, flags);
1413
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1414
+ // @ts-ignore
1415
+ let content = $el?.textContent || $el?.innerText;
1416
+ if (typeof content !== "string") {
1417
+ content = "";
1418
+ }
1419
+ return $el.matches(selector) && Boolean(content?.match(regexp));
1420
+ } else {
1421
+ // 普通语法
1422
+ return $el.matches(selector);
1423
+ }
1424
+ }
1425
+ /**
1426
+ * 根据选择器获取上层元素,可使用以下的额外语法
1427
+ *
1428
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1429
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1430
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1431
+ * @param $el 元素
1432
+ * @param selector 选择器
1433
+ * @example
1434
+ * DOMUtils.closest("div:contains('测试')")
1435
+ * > div.xxx
1436
+ * @example
1437
+ * DOMUtils.closest("div:empty")
1438
+ * > div.xxx
1439
+ * @example
1440
+ * DOMUtils.closest("div:regexp('^xxxx$')")
1441
+ * > div.xxxx
1442
+ * @example
1443
+ * DOMUtils.closest("div:regexp(/^xxx/ig)")
1444
+ * > null
1445
+ */
1446
+ closest<K extends keyof HTMLElementTagNameMap>(
1447
+ $el: HTMLElement | Element,
1448
+ selector: string
1449
+ ): HTMLElementTagNameMap[K] | null;
1450
+ closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null;
1451
+ closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null {
1452
+ selector = selector.trim();
1486
1453
 
1487
- if (selector.match(/[^\s]{1}:empty$/gi)) {
1488
- // empty 语法
1489
- selector = selector.replace(/:empty$/gi, "");
1490
- let $closest = $el?.closest<E>(selector);
1491
- if ($closest && $closest?.innerHTML?.trim() === "") {
1492
- return $closest;
1493
- }
1494
- return null;
1495
- } else if (
1496
- selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
1497
- selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
1498
- ) {
1499
- // contains 语法
1500
- let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1501
- let text = textMatch![2];
1502
- selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1503
- let $closest = $el?.closest<E>(selector);
1504
- if ($closest) {
1505
- // @ts-ignore
1506
- let content = $el?.textContent || $el?.innerText;
1507
- if (typeof content === "string" && content.includes(text)) {
1508
- return $closest;
1509
- }
1510
- }
1511
- return null;
1512
- } else if (
1513
- selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
1514
- selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
1515
- ) {
1516
- // regexp 语法
1517
- let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1518
- let pattern = textMatch![2];
1519
- let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1520
- let flags = "";
1521
- if (flagMatch) {
1522
- pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1523
- flags = flagMatch[3];
1524
- }
1525
- let regexp = new RegExp(pattern, flags);
1526
- selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1527
- let $closest = $el?.closest<E>(selector);
1528
- if ($closest) {
1529
- // @ts-ignore
1530
- let content = $el?.textContent || $el?.innerText;
1531
- if (typeof content === "string" && content.match(regexp)) {
1532
- return $closest;
1533
- }
1534
- }
1535
- return null;
1536
- } else {
1537
- // 普通语法
1538
- let $closest = $el?.closest<E>(selector);
1539
- return $closest;
1540
- }
1541
- }
1454
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1455
+ // empty 语法
1456
+ selector = selector.replace(/:empty$/gi, "");
1457
+ const $closest = $el?.closest<E>(selector);
1458
+ if ($closest && $closest?.innerHTML?.trim() === "") {
1459
+ return $closest;
1460
+ }
1461
+ return null;
1462
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
1463
+ // contains 语法
1464
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1465
+ const text = textMatch![2];
1466
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1467
+ const $closest = $el?.closest<E>(selector);
1468
+ if ($closest) {
1469
+ // @ts-ignore
1470
+ const content = $el?.textContent || $el?.innerText;
1471
+ if (typeof content === "string" && content.includes(text)) {
1472
+ return $closest;
1473
+ }
1474
+ }
1475
+ return null;
1476
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
1477
+ // regexp 语法
1478
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1479
+ let pattern = textMatch![2];
1480
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1481
+ let flags = "";
1482
+ if (flagMatch) {
1483
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1484
+ flags = flagMatch[3];
1485
+ }
1486
+ const regexp = new RegExp(pattern, flags);
1487
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1488
+ const $closest = $el?.closest<E>(selector);
1489
+ if ($closest) {
1490
+ // @ts-ignore
1491
+ const content = $el?.textContent || $el?.innerText;
1492
+ if (typeof content === "string" && content.match(regexp)) {
1493
+ return $closest;
1494
+ }
1495
+ }
1496
+ return null;
1497
+ } else {
1498
+ // 普通语法
1499
+ const $closest = $el?.closest<E>(selector);
1500
+ return $closest;
1501
+ }
1502
+ }
1542
1503
  }