@whitesev/domutils 1.6.5 → 1.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,1174 +2,1140 @@ 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" && "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
+ elementList.forEach((elementItem) => {
511
+ /* 获取对象上的事件 */
512
+ const elementEvents: {
513
+ [key: string]: DOMUtilsEventListenerOptionsAttribute[];
514
+ } = Reflect.get(elementItem, DOMUtilsData.SymbolEvents) || {};
515
+ eventTypeList.forEach((eventName) => {
516
+ let handlers = elementEvents[eventName] || [];
517
+ if (typeof filter === "function") {
518
+ handlers = handlers.filter(filter);
519
+ }
520
+ for (let index = 0; index < handlers.length; index++) {
521
+ const handler = handlers[index];
522
+ let flag = true;
523
+ if (flag && listenerCallBack && handler.originCallBack !== listenerCallBack) {
524
+ // callback不同
525
+ flag = false;
526
+ }
527
+ if (flag && selectorList.length && Array.isArray(handler.selector)) {
528
+ if (JSON.stringify(handler.selector) !== JSON.stringify(selectorList)) {
529
+ // 子元素选择器不同
530
+ flag = false;
531
+ }
532
+ }
533
+ if (flag && listenerOption.capture !== handler.option.capture) {
534
+ // 事件的配置项不同
535
+ flag = false;
536
+ }
537
+ if (flag || isRemoveAll) {
538
+ elementItem.removeEventListener(eventName, handler.callback, handler.option);
539
+ handlers.splice(index--, 1);
540
+ }
541
+ }
542
+ if (handlers.length === 0) {
543
+ /* 如果没有任意的handler,那么删除该属性 */
544
+ DOMUtilsCommonUtils.delete(elementEvents, eventType);
545
+ }
546
+ });
547
+ Reflect.set(elementItem, DOMUtilsData.SymbolEvents, elementEvents);
548
+ });
549
+ }
550
+ /**
551
+ * 取消绑定所有的事件
552
+ * @param element 需要取消绑定的元素|元素数组
553
+ * @param eventType (可选)需要取消监听的事件
554
+ */
555
+ offAll(element: DOMUtilsElementEventType, eventType?: string): void;
556
+ /**
557
+ * 取消绑定所有的事件
558
+ * @param element 需要取消绑定的元素|元素数组
559
+ * @param eventType (可选)需要取消监听的事件
560
+ */
561
+ offAll(element: DOMUtilsElementEventType, eventType?: DOMUtils_EventType | DOMUtils_EventType[]): void;
562
+ /**
563
+ * 取消绑定所有的事件
564
+ * @param element 需要取消绑定的元素|元素数组
565
+ * @param eventType (可选)需要取消监听的事件
566
+ */
567
+ offAll(element: DOMUtilsElementEventType, eventType?: DOMUtils_EventType | DOMUtils_EventType[] | string) {
568
+ const DOMUtilsContext = this;
569
+ if (typeof element === "string") {
570
+ element = DOMUtilsContext.selectorAll(element);
571
+ }
572
+ if (element == null) {
573
+ return;
574
+ }
575
+ let elementList: HTMLElement[] = [];
576
+ if (element instanceof NodeList || Array.isArray(element)) {
577
+ elementList = [...(element as HTMLElement[])];
578
+ } else {
579
+ elementList.push(element as HTMLElement);
580
+ }
608
581
 
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
- }
582
+ let eventTypeList: string[] = [];
583
+ if (Array.isArray(eventType)) {
584
+ eventTypeList = eventTypeList.concat(eventType as string[]);
585
+ } else if (typeof eventType === "string") {
586
+ eventTypeList = eventTypeList.concat(eventType.split(" "));
587
+ }
588
+ elementList.forEach((elementItem) => {
589
+ Object.getOwnPropertySymbols(elementItem).forEach((symbolEvents) => {
590
+ if (!symbolEvents.toString().startsWith("Symbol(events_")) {
591
+ return;
592
+ }
593
+ const elementEvents = (elementItem as any)[symbolEvents] || {};
594
+ const iterEventNameList = eventTypeList.length ? eventTypeList : Object.keys(elementEvents);
595
+ iterEventNameList.forEach((eventName) => {
596
+ const handlers: DOMUtilsEventListenerOptionsAttribute[] = elementEvents[eventName];
597
+ if (!handlers) {
598
+ return;
599
+ }
600
+ for (const handler of handlers) {
601
+ elementItem.removeEventListener(eventName, handler.callback, {
602
+ capture: handler["option"]["capture"],
603
+ });
604
+ }
605
+ const events = Reflect.get(elementItem, symbolEvents);
606
+ DOMUtilsCommonUtils.delete(events, eventName);
607
+ });
608
+ });
609
+ });
610
+ }
638
611
 
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
- }
612
+ /**
613
+ * 等待文档加载完成后执行指定的函数
614
+ * @param callback 需要执行的函数
615
+ * @example
616
+ * DOMUtils.ready(function(){
617
+ * console.log("文档加载完毕")
618
+ * })
619
+ */
620
+ ready<T extends (...args: any[]) => any>(callback: T) {
621
+ if (typeof callback !== "function") {
622
+ return;
623
+ }
624
+ const DOMUtilsContext = this;
625
+ /**
626
+ * 检测文档是否加载完毕
627
+ */
628
+ function checkDOMReadyState() {
629
+ try {
630
+ if (
631
+ DOMUtilsContext.windowApi.document.readyState === "complete" ||
632
+ (DOMUtilsContext.windowApi.document.readyState !== "loading" &&
633
+ !(DOMUtilsContext.windowApi.document.documentElement as any).doScroll)
634
+ ) {
635
+ return true;
636
+ } else {
637
+ return false;
638
+ }
639
+ } catch {
640
+ return false;
641
+ }
642
+ }
643
+ /**
644
+ * 成功加载完毕后触发的回调函数
645
+ */
646
+ function completed() {
647
+ removeDomReadyListener();
648
+ callback();
649
+ }
677
650
 
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
- }
651
+ const targetList = [
652
+ {
653
+ target: DOMUtilsContext.windowApi.document,
654
+ eventType: "DOMContentLoaded",
655
+ callback: completed,
656
+ },
657
+ {
658
+ target: DOMUtilsContext.windowApi.window,
659
+ eventType: "load",
660
+ callback: completed,
661
+ },
662
+ ];
663
+ /**
664
+ * 添加监听
665
+ */
666
+ function addDomReadyListener() {
667
+ for (let index = 0; index < targetList.length; index++) {
668
+ const item = targetList[index];
669
+ item.target.addEventListener(item.eventType, item.callback);
670
+ }
671
+ }
672
+ /**
673
+ * 移除监听
674
+ */
675
+ function removeDomReadyListener() {
676
+ for (let index = 0; index < targetList.length; index++) {
677
+ const item = targetList[index];
678
+ item.target.removeEventListener(item.eventType, item.callback);
679
+ }
680
+ }
681
+ if (checkDOMReadyState()) {
682
+ /* 检查document状态 */
683
+ DOMUtilsCommonUtils.setTimeout(callback);
684
+ } else {
685
+ /* 添加监听 */
686
+ addDomReadyListener();
687
+ }
688
+ }
689
+ /**
690
+ * 主动触发事件
691
+ * @param element 需要触发的元素|元素数组|window
692
+ * @param eventType 需要触发的事件
693
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
694
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
695
+ * @example
696
+ * // 触发元素a.xx的click事件
697
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
698
+ * DOMUtils.trigger("a.xx","click")
699
+ * // 触发元素a.xx的click、tap、hover事件
700
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
701
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
702
+ */
703
+ trigger(
704
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | any[] | typeof globalThis | Window | Document,
705
+ eventType: string,
706
+ details?: object,
707
+ useDispatchToTriggerEvent?: boolean
708
+ ): void;
709
+ /**
710
+ * 主动触发事件
711
+ * @param element 需要触发的元素|元素数组|window
712
+ * @param eventType 需要触发的事件
713
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
714
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
715
+ * @example
716
+ * // 触发元素a.xx的click事件
717
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
718
+ * DOMUtils.trigger("a.xx","click")
719
+ * // 触发元素a.xx的click、tap、hover事件
720
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
721
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
722
+ */
723
+ trigger(
724
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
725
+ eventType: DOMUtils_EventType | DOMUtils_EventType[],
726
+ details?: object,
727
+ useDispatchToTriggerEvent?: boolean
728
+ ): void;
729
+ /**
730
+ * 主动触发事件
731
+ * @param element 需要触发的元素|元素数组|window
732
+ * @param eventType 需要触发的事件
733
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
734
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
735
+ * @example
736
+ * // 触发元素a.xx的click事件
737
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
738
+ * DOMUtils.trigger("a.xx","click")
739
+ * // 触发元素a.xx的click、tap、hover事件
740
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
741
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
742
+ */
743
+ trigger(
744
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
745
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
746
+ details?: object,
747
+ useDispatchToTriggerEvent: boolean = true
748
+ ) {
749
+ const DOMUtilsContext = this;
750
+ if (typeof element === "string") {
751
+ element = DOMUtilsContext.selectorAll(element);
752
+ }
753
+ if (element == null) {
754
+ return;
755
+ }
756
+ let elementList = [];
757
+ if (element instanceof NodeList || Array.isArray(element)) {
758
+ element = element as HTMLElement[];
759
+ elementList = [...element];
760
+ } else {
761
+ elementList = [element];
762
+ }
763
+ let eventTypeList: string[] = [];
764
+ if (Array.isArray(eventType)) {
765
+ eventTypeList = eventType as string[];
766
+ } else if (typeof eventType === "string") {
767
+ eventTypeList = eventType.split(" ");
768
+ }
803
769
 
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
- }
770
+ elementList.forEach((elementItem) => {
771
+ /* 获取对象上的事件 */
772
+ const events = elementItem[DOMUtilsData.SymbolEvents] || {};
773
+ eventTypeList.forEach((_eventType_) => {
774
+ let event: Event = null as any;
775
+ if (details && details instanceof Event) {
776
+ event = details;
777
+ } else {
778
+ event = new Event(_eventType_);
779
+ if (details) {
780
+ Object.keys(details).forEach((keyName) => {
781
+ (event as any)[keyName] = (details as any)[keyName];
782
+ });
783
+ }
784
+ }
785
+ if (useDispatchToTriggerEvent == false && _eventType_ in events) {
786
+ events[_eventType_].forEach((eventsItem: any) => {
787
+ eventsItem.callback(event);
788
+ });
789
+ } else {
790
+ elementItem.dispatchEvent(event);
791
+ }
792
+ });
793
+ });
794
+ }
829
795
 
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
- /**
796
+ /**
797
+ * 绑定或触发元素的click事件
798
+ * @param element 目标元素
799
+ * @param handler (可选)事件处理函数
800
+ * @param details (可选)赋予触发的Event的额外属性
801
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
802
+ * @example
803
+ * // 触发元素a.xx的click事件
804
+ * DOMUtils.click(document.querySelector("a.xx"))
805
+ * DOMUtils.click("a.xx")
806
+ * DOMUtils.click("a.xx",function(){
807
+ * console.log("触发click事件成功")
808
+ * })
809
+ * */
810
+ click(
811
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
812
+ handler?: (this: HTMLElement, event: DOMUtils_Event["click"]) => void,
813
+ details?: any,
814
+ useDispatchToTriggerEvent?: boolean
815
+ ) {
816
+ const DOMUtilsContext = this;
817
+ if (typeof element === "string") {
818
+ element = DOMUtilsContext.selectorAll(element);
819
+ }
820
+ if (element == null) {
821
+ return;
822
+ }
823
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
824
+ // 设置
825
+ element.forEach(($ele) => {
826
+ DOMUtilsContext.click($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
827
+ });
828
+ return;
829
+ }
830
+ if (handler == null) {
831
+ DOMUtilsContext.trigger(element, "click", details, useDispatchToTriggerEvent);
832
+ } else {
833
+ DOMUtilsContext.on(element, "click", null, handler);
834
+ }
835
+ }
836
+ /**
837
+ * 绑定或触发元素的blur事件
838
+ * @param element 目标元素
839
+ * @param handler (可选)事件处理函数
840
+ * @param details (可选)赋予触发的Event的额外属性
841
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
842
+ * @example
843
+ * // 触发元素a.xx的blur事件
844
+ * DOMUtils.blur(document.querySelector("a.xx"))
845
+ * DOMUtils.blur("a.xx")
846
+ * DOMUtils.blur("a.xx",function(){
847
+ * console.log("触发blur事件成功")
848
+ * })
849
+ * */
850
+ blur(
851
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
852
+ handler?: (this: HTMLElement, event: DOMUtils_Event["blur"]) => void,
853
+ details?: object,
854
+ useDispatchToTriggerEvent?: boolean
855
+ ) {
856
+ const DOMUtilsContext = this;
857
+ if (typeof element === "string") {
858
+ element = DOMUtilsContext.selectorAll(element);
859
+ }
860
+ if (element == null) {
861
+ return;
862
+ }
863
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
864
+ // 设置
865
+ element.forEach(($ele) => {
866
+ DOMUtilsContext.focus($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
867
+ });
868
+ return;
869
+ }
870
+ if (handler === null) {
871
+ DOMUtilsContext.trigger(element, "blur", details, useDispatchToTriggerEvent);
872
+ } else {
873
+ DOMUtilsContext.on(element, "blur", null, handler as (event: Event) => void);
874
+ }
875
+ }
876
+ /**
877
+ * 绑定或触发元素的focus事件
878
+ * @param element 目标元素
879
+ * @param handler (可选)事件处理函数
880
+ * @param details (可选)赋予触发的Event的额外属性
881
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
882
+ * @example
883
+ * // 触发元素a.xx的focus事件
884
+ * DOMUtils.focus(document.querySelector("a.xx"))
885
+ * DOMUtils.focus("a.xx")
886
+ * DOMUtils.focus("a.xx",function(){
887
+ * console.log("触发focus事件成功")
888
+ * })
889
+ * */
890
+ focus(
891
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | typeof globalThis | Window,
892
+ handler?: (this: HTMLElement, event: DOMUtils_Event["focus"]) => void,
893
+ details?: object,
894
+ useDispatchToTriggerEvent?: boolean
895
+ ) {
896
+ const DOMUtilsContext = this;
897
+ if (typeof element === "string") {
898
+ element = DOMUtilsContext.selectorAll(element);
899
+ }
900
+ if (element == null) {
901
+ return;
902
+ }
903
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
904
+ // 设置
905
+ element.forEach(($ele) => {
906
+ DOMUtilsContext.focus($ele as HTMLElement, handler, details, useDispatchToTriggerEvent);
907
+ });
908
+ return;
909
+ }
910
+ if (handler == null) {
911
+ DOMUtilsContext.trigger(element, "focus", details, useDispatchToTriggerEvent);
912
+ } else {
913
+ DOMUtilsContext.on(element, "focus", null, handler);
914
+ }
915
+ }
916
+ /**
917
+ * 当鼠标移入或移出元素时触发事件
918
+ * @param element 当前元素
919
+ * @param handler 事件处理函数
920
+ * @param option 配置
921
+ * @example
922
+ * // 监听a.xx元素的移入或移出
923
+ * DOMUtils.hover(document.querySelector("a.xx"),()=>{
924
+ * console.log("移入/移除");
925
+ * })
926
+ * DOMUtils.hover("a.xx",()=>{
927
+ * console.log("移入/移除");
928
+ * })
929
+ */
930
+ hover(
931
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Node,
932
+ handler: (this: HTMLElement, event: DOMUtils_Event["hover"]) => void,
933
+ option?: boolean | DOMUtilsEventListenerOption
934
+ ) {
935
+ const DOMUtilsContext = this;
936
+ if (typeof element === "string") {
937
+ element = DOMUtilsContext.selectorAll(element);
938
+ }
939
+ if (element == null) {
940
+ return;
941
+ }
942
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
943
+ // 设置
944
+ element.forEach(($ele) => {
945
+ DOMUtilsContext.hover($ele as HTMLElement, handler, option);
946
+ });
947
+ return;
948
+ }
949
+ DOMUtilsContext.on(element, "mouseenter", null, handler, option);
950
+ DOMUtilsContext.on(element, "mouseleave", null, handler, option);
951
+ }
952
+ /**
953
+ * 当动画结束时触发事件
954
+ * @param element 监听的元素
955
+ * @param handler 触发的回调函数
956
+ * @param option 配置项,这里默认配置once为true
957
+ */
958
+ animationend(
959
+ element: HTMLElement | string | Element | DocumentFragment,
960
+ handler: (this: HTMLElement, event: DOMUtils_Event["animationend"]) => void,
961
+ option?: boolean | DOMUtilsEventListenerOption
962
+ ) {
963
+ const DOMUtilsContext = this;
964
+ if (typeof element === "string") {
965
+ element = DOMUtilsContext.selector(element)!;
966
+ }
967
+ if (element == null) {
968
+ return;
969
+ }
970
+ // if (DOMUtilsCommonUtils.isNodeList(element)) {
971
+ // // 设置
972
+ // element.forEach(($ele) => {
973
+ // DOMUtilsContext.animationend($ele as HTMLElement, handler, option);
974
+ // });
975
+ // return;
976
+ // }
977
+ const defaultOption: DOMUtilsEventListenerOption = {
978
+ once: true,
979
+ };
980
+ Object.assign(defaultOption, option || {});
981
+ const eventNameList = DOMUtilsCommonUtils.getAnimationEndNameList();
982
+ DOMUtilsContext.on(element, eventNameList, null, handler, defaultOption);
983
+ if (!defaultOption.once) {
984
+ return {
985
+ off() {
986
+ DOMUtilsContext.off(element, eventNameList, null, handler, defaultOption);
987
+ },
988
+ };
989
+ }
990
+ }
991
+ /**
992
+ * 当过渡结束时触发事件
993
+ * @param element 监听的元素
994
+ * @param handler 触发的回调函数
995
+ * @param option 配置项,这里默认配置once为true
996
+ */
997
+ transitionend(
998
+ element: HTMLElement | string | Element | DocumentFragment,
999
+ handler: (this: HTMLElement, event: DOMUtils_Event["transitionend"]) => void,
1000
+ option?: boolean | DOMUtilsEventListenerOption
1001
+ ) {
1002
+ const DOMUtilsContext = this;
1003
+ if (typeof element === "string") {
1004
+ element = DOMUtilsContext.selector(element)!;
1005
+ }
1006
+ if (element == null) {
1007
+ return;
1008
+ }
1009
+ // if (DOMUtilsCommonUtils.isNodeList(element)) {
1010
+ // // 设置
1011
+ // element.forEach(($ele) => {
1012
+ // DOMUtilsContext.transitionend($ele as HTMLElement, handler, option);
1013
+ // });
1014
+ // return;
1015
+ // }
1016
+ const defaultOption: DOMUtilsEventListenerOption = {
1017
+ once: true,
1018
+ };
1019
+ Object.assign(defaultOption, option || {});
1020
+ const eventNameList = DOMUtilsCommonUtils.getTransitionEndNameList();
1021
+ DOMUtilsContext.on(element, eventNameList, null, handler, defaultOption);
1022
+ if (!defaultOption.once) {
1023
+ return {
1024
+ off() {
1025
+ DOMUtilsContext.off(element, eventNameList, null, handler, defaultOption);
1026
+ },
1027
+ };
1028
+ }
1029
+ }
1030
+ /**
1031
+ * 当按键松开时触发事件
1032
+ * keydown - > keypress - > keyup
1033
+ * @param element 当前元素
1034
+ * @param handler 事件处理函数
1035
+ * @param option 配置
1036
+ * @example
1037
+ * // 监听a.xx元素的按键松开
1038
+ * DOMUtils.keyup(document.querySelector("a.xx"),()=>{
1039
+ * console.log("按键松开");
1040
+ * })
1041
+ * DOMUtils.keyup("a.xx",()=>{
1042
+ * console.log("按键松开");
1043
+ * })
1044
+ */
1045
+ keyup(
1046
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1047
+ handler: (this: HTMLElement, event: DOMUtils_Event["keyup"]) => void,
1048
+ option?: boolean | DOMUtilsEventListenerOption
1049
+ ) {
1050
+ const DOMUtilsContext = this;
1051
+ if (element == null) {
1052
+ return;
1053
+ }
1054
+ if (typeof element === "string") {
1055
+ element = DOMUtilsContext.selectorAll(element);
1056
+ }
1057
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1058
+ // 设置
1059
+ element.forEach(($ele) => {
1060
+ DOMUtilsContext.keyup($ele as HTMLElement, handler, option);
1061
+ });
1062
+ return;
1063
+ }
1064
+ DOMUtilsContext.on(element, "keyup", null, handler, option);
1065
+ }
1066
+ /**
1067
+ * 当按键按下时触发事件
1068
+ * keydown - > keypress - > keyup
1069
+ * @param element 目标
1070
+ * @param handler 事件处理函数
1071
+ * @param option 配置
1072
+ * @example
1073
+ * // 监听a.xx元素的按键按下
1074
+ * DOMUtils.keydown(document.querySelector("a.xx"),()=>{
1075
+ * console.log("按键按下");
1076
+ * })
1077
+ * DOMUtils.keydown("a.xx",()=>{
1078
+ * console.log("按键按下");
1079
+ * })
1080
+ */
1081
+ keydown(
1082
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1083
+ handler: (this: HTMLElement, event: DOMUtils_Event["keydown"]) => void,
1084
+ option?: boolean | DOMUtilsEventListenerOption
1085
+ ) {
1086
+ const DOMUtilsContext = this;
1087
+ if (element == null) {
1088
+ return;
1089
+ }
1090
+ if (typeof element === "string") {
1091
+ element = DOMUtilsContext.selectorAll(element);
1092
+ }
1093
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1094
+ // 设置
1095
+ element.forEach(($ele) => {
1096
+ DOMUtilsContext.keydown($ele as HTMLElement, handler, option);
1097
+ });
1098
+ return;
1099
+ }
1100
+ DOMUtilsContext.on(element, "keydown", null, handler, option);
1101
+ }
1102
+ /**
1103
+ * 当按键按下时触发事件
1104
+ * keydown - > keypress - > keyup
1105
+ * @param element 目标
1106
+ * @param handler 事件处理函数
1107
+ * @param option 配置
1108
+ * @example
1109
+ * // 监听a.xx元素的按键按下
1110
+ * DOMUtils.keypress(document.querySelector("a.xx"),()=>{
1111
+ * console.log("按键按下");
1112
+ * })
1113
+ * DOMUtils.keypress("a.xx",()=>{
1114
+ * console.log("按键按下");
1115
+ * })
1116
+ */
1117
+ keypress(
1118
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1119
+ handler: (this: HTMLElement, event: DOMUtils_Event["keypress"]) => void,
1120
+ option?: boolean | DOMUtilsEventListenerOption
1121
+ ) {
1122
+ const DOMUtilsContext = this;
1123
+ if (element == null) {
1124
+ return;
1125
+ }
1126
+ if (typeof element === "string") {
1127
+ element = DOMUtilsContext.selectorAll(element);
1128
+ }
1129
+ if (DOMUtilsCommonUtils.isNodeList(element)) {
1130
+ // 设置
1131
+ element.forEach(($ele) => {
1132
+ DOMUtilsContext.keypress($ele as HTMLElement, handler, option);
1133
+ });
1134
+ return;
1135
+ }
1136
+ DOMUtilsContext.on(element, "keypress", null, handler, option);
1137
+ }
1138
+ /**
1173
1139
  * 监听某个元素键盘按键事件或window全局按键事件
1174
1140
  * 按下有值的键时触发,按下Ctrl\Alt\Shift\Meta是无值键。按下先触发keydown事件,再触发keypress事件。
1175
1141
  * @param element 需要监听的对象,可以是全局Window或者某个元素
@@ -1232,311 +1198,293 @@ export class DOMUtilsEvent {
1232
1198
  搜索 170
1233
1199
  收藏 171
1234
1200
  **/
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 = Element>(
1300
- selector: string,
1301
- parent?: Element | Document | DocumentFragment | ShadowRoot
1302
- ): E | undefined;
1303
- selector<E extends Element = Element>(
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 = Element>(
1335
- selector: string,
1336
- parent?: Element | Document | DocumentFragment | ShadowRoot
1337
- ): E[];
1338
- selectorAll<E extends Element = Element>(
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
- }
1201
+ listenKeyboard(
1202
+ element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1203
+ eventName: "keyup" | "keypress" | "keydown" = "keypress",
1204
+ callback: (keyName: string, keyValue: number, otherCodeList: string[], event: KeyboardEvent) => void,
1205
+ options?: DOMUtilsEventListenerOption | boolean
1206
+ ): {
1207
+ removeListen(): void;
1208
+ } {
1209
+ const DOMUtilsContext = this;
1210
+ if (typeof element === "string") {
1211
+ element = DOMUtilsContext.selectorAll(element);
1212
+ }
1213
+ const keyboardEventCallBack = function (event: KeyboardEvent) {
1214
+ /** 键名 */
1215
+ const keyName = event.key || event.code;
1216
+ /** 键值 */
1217
+ const keyValue = event.charCode || event.keyCode || event.which;
1218
+ /** 组合键列表 */
1219
+ const otherCodeList: string[] = [];
1220
+ if (event.ctrlKey) {
1221
+ otherCodeList.push("ctrl");
1222
+ }
1223
+ if (event.altKey) {
1224
+ otherCodeList.push("alt");
1225
+ }
1226
+ if (event.metaKey) {
1227
+ otherCodeList.push("meta");
1228
+ }
1229
+ if (event.shiftKey) {
1230
+ otherCodeList.push("shift");
1231
+ }
1232
+ if (typeof callback === "function") {
1233
+ callback(keyName, keyValue, otherCodeList, event);
1234
+ }
1235
+ };
1236
+ DOMUtilsContext.on(element, eventName, keyboardEventCallBack, options);
1237
+ return {
1238
+ removeListen: () => {
1239
+ DOMUtilsContext.off(element, eventName, keyboardEventCallBack, options);
1240
+ },
1241
+ };
1242
+ }
1243
+ /**
1244
+ * 选择器,可使用以下的额外语法
1245
+ *
1246
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1247
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1248
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1249
+ * @param selector 选择器
1250
+ * @param parent 指定父元素
1251
+ * @example
1252
+ * DOMUtils.selector("div:contains('测试')")
1253
+ * > div.xxx
1254
+ * @example
1255
+ * DOMUtils.selector("div:empty")
1256
+ * > div.xxx
1257
+ * @example
1258
+ * DOMUtils.selector("div:regexp('^xxxx$')")
1259
+ * > div.xxx
1260
+ */
1261
+ selector<K extends keyof HTMLElementTagNameMap>(
1262
+ selector: K,
1263
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1264
+ ): HTMLElementTagNameMap[K] | undefined;
1265
+ selector<E extends Element = HTMLElement>(
1266
+ selector: string,
1267
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1268
+ ): E | undefined;
1269
+ selector<E extends Element = HTMLElement>(
1270
+ selector: string,
1271
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1272
+ ) {
1273
+ return this.selectorAll<E>(selector, parent)[0];
1274
+ }
1275
+ /**
1276
+ * 选择器,可使用以下的额外语法
1277
+ *
1278
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1279
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1280
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1281
+ * @param selector 选择器
1282
+ * @param parent 指定父元素
1283
+ * @example
1284
+ * DOMUtils.selectorAll("div:contains('测试')")
1285
+ * > [div.xxx]
1286
+ * @example
1287
+ * DOMUtils.selectorAll("div:empty")
1288
+ * > [div.xxx]
1289
+ * @example
1290
+ * DOMUtils.selectorAll("div:regexp('^xxxx$')")
1291
+ * > [div.xxx]
1292
+ * @example
1293
+ * DOMUtils.selectorAll("div:regexp(/^xxx/ig)")
1294
+ * > [div.xxx]
1295
+ */
1296
+ selectorAll<K extends keyof HTMLElementTagNameMap>(
1297
+ selector: K,
1298
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1299
+ ): HTMLElementTagNameMap[K][];
1300
+ selectorAll<E extends Element = HTMLElement>(
1301
+ selector: string,
1302
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1303
+ ): E[];
1304
+ selectorAll<E extends Element = HTMLElement>(
1305
+ selector: string,
1306
+ parent?: Element | Document | DocumentFragment | ShadowRoot
1307
+ ) {
1308
+ const context = this;
1309
+ parent = parent || context.windowApi.document;
1310
+ selector = selector.trim();
1311
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1312
+ // empty 语法
1313
+ selector = selector.replace(/:empty$/gi, "");
1314
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1315
+ return $ele?.innerHTML?.trim() === "";
1316
+ });
1317
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
1318
+ // contains 语法
1319
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1320
+ const text = textMatch![2];
1321
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1322
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1323
+ // @ts-ignore
1324
+ return ($ele?.textContent || $ele?.innerText)?.includes(text);
1325
+ });
1326
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
1327
+ // regexp 语法
1328
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1329
+ let pattern = textMatch![2];
1330
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1331
+ let flags = "";
1332
+ if (flagMatch) {
1333
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1334
+ flags = flagMatch[3];
1335
+ }
1336
+ const regexp = new RegExp(pattern, flags);
1337
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1338
+ return Array.from(parent.querySelectorAll<E>(selector)).filter(($ele) => {
1339
+ // @ts-ignore
1340
+ return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
1341
+ });
1342
+ } else {
1343
+ // 普通语法
1344
+ return Array.from(parent.querySelectorAll<E>(selector));
1345
+ }
1346
+ }
1347
+ /**
1348
+ * 匹配元素,可使用以下的额外语法
1349
+ *
1350
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1351
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1352
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1353
+ * @param $el 元素
1354
+ * @param selector 选择器
1355
+ * @example
1356
+ * DOMUtils.matches("div:contains('测试')")
1357
+ * > true
1358
+ * @example
1359
+ * DOMUtils.matches("div:empty")
1360
+ * > true
1361
+ * @example
1362
+ * DOMUtils.matches("div:regexp('^xxxx$')")
1363
+ * > true
1364
+ * @example
1365
+ * DOMUtils.matches("div:regexp(/^xxx/ig)")
1366
+ * > false
1367
+ */
1368
+ matches($el: HTMLElement | Element | null | undefined, selector: string): boolean {
1369
+ selector = selector.trim();
1370
+ if ($el == null) {
1371
+ return false;
1372
+ }
1413
1373
 
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();
1374
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1375
+ // empty 语法
1376
+ selector = selector.replace(/:empty$/gi, "");
1377
+ return $el.matches(selector) && $el?.innerHTML?.trim() === "";
1378
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
1379
+ // contains 语法
1380
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1381
+ const text = textMatch![2];
1382
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1383
+ // @ts-ignore
1384
+ let content = $el?.textContent || $el?.innerText;
1385
+ if (typeof content !== "string") {
1386
+ content = "";
1387
+ }
1388
+ return $el.matches(selector) && content?.includes(text);
1389
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
1390
+ // regexp 语法
1391
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1392
+ let pattern = textMatch![2];
1393
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1394
+ let flags = "";
1395
+ if (flagMatch) {
1396
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1397
+ flags = flagMatch[3];
1398
+ }
1399
+ const regexp = new RegExp(pattern, flags);
1400
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1401
+ // @ts-ignore
1402
+ let content = $el?.textContent || $el?.innerText;
1403
+ if (typeof content !== "string") {
1404
+ content = "";
1405
+ }
1406
+ return $el.matches(selector) && Boolean(content?.match(regexp));
1407
+ } else {
1408
+ // 普通语法
1409
+ return $el.matches(selector);
1410
+ }
1411
+ }
1412
+ /**
1413
+ * 根据选择器获取上层元素,可使用以下的额外语法
1414
+ *
1415
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1416
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1417
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1418
+ * @param $el 元素
1419
+ * @param selector 选择器
1420
+ * @example
1421
+ * DOMUtils.closest("div:contains('测试')")
1422
+ * > div.xxx
1423
+ * @example
1424
+ * DOMUtils.closest("div:empty")
1425
+ * > div.xxx
1426
+ * @example
1427
+ * DOMUtils.closest("div:regexp('^xxxx$')")
1428
+ * > div.xxxx
1429
+ * @example
1430
+ * DOMUtils.closest("div:regexp(/^xxx/ig)")
1431
+ * > null
1432
+ */
1433
+ closest<K extends keyof HTMLElementTagNameMap>(
1434
+ $el: HTMLElement | Element,
1435
+ selector: string
1436
+ ): HTMLElementTagNameMap[K] | null;
1437
+ closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null;
1438
+ closest<E extends Element = Element>($el: HTMLElement | Element, selector: string): E | null {
1439
+ selector = selector.trim();
1486
1440
 
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
- }
1441
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1442
+ // empty 语法
1443
+ selector = selector.replace(/:empty$/gi, "");
1444
+ const $closest = $el?.closest<E>(selector);
1445
+ if ($closest && $closest?.innerHTML?.trim() === "") {
1446
+ return $closest;
1447
+ }
1448
+ return null;
1449
+ } else if (selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) || selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)) {
1450
+ // contains 语法
1451
+ const textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1452
+ const text = textMatch![2];
1453
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1454
+ const $closest = $el?.closest<E>(selector);
1455
+ if ($closest) {
1456
+ // @ts-ignore
1457
+ const content = $el?.textContent || $el?.innerText;
1458
+ if (typeof content === "string" && content.includes(text)) {
1459
+ return $closest;
1460
+ }
1461
+ }
1462
+ return null;
1463
+ } else if (selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) || selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)) {
1464
+ // regexp 语法
1465
+ const textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1466
+ let pattern = textMatch![2];
1467
+ const flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1468
+ let flags = "";
1469
+ if (flagMatch) {
1470
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1471
+ flags = flagMatch[3];
1472
+ }
1473
+ const regexp = new RegExp(pattern, flags);
1474
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1475
+ const $closest = $el?.closest<E>(selector);
1476
+ if ($closest) {
1477
+ // @ts-ignore
1478
+ const content = $el?.textContent || $el?.innerText;
1479
+ if (typeof content === "string" && content.match(regexp)) {
1480
+ return $closest;
1481
+ }
1482
+ }
1483
+ return null;
1484
+ } else {
1485
+ // 普通语法
1486
+ const $closest = $el?.closest<E>(selector);
1487
+ return $closest;
1488
+ }
1489
+ }
1542
1490
  }