@whitesev/pops 2.0.11 → 2.0.13

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.
@@ -1,15 +1,14 @@
1
1
  import type {
2
2
  ParseHTMLReturnType,
3
+ PopsDOMUtils_EventType,
3
4
  PopsDOMUtilsCreateElementAttributesMap,
4
- } from "../types/PopsDOMUtilsEventType";
5
- import { SymbolEvents } from "../Config";
6
- import { OriginPrototype, PopsCore } from "../Core";
7
- import type {
5
+ PopsDOMUtilsEventListenerOption,
6
+ PopsDOMUtilsEventListenerOptionsAttribute,
8
7
  PopsDOMUtils_Event,
9
- PopsDOMUtils_EventType,
10
8
  PopsDOMUtilsElementEventType,
11
- PopsDOMUtilsEventListenerOptionsAttribute,
12
9
  } from "../types/PopsDOMUtilsEventType";
10
+ import { SymbolEvents } from "../Config";
11
+ import { OriginPrototype, PopsCore } from "../Core";
13
12
  import { popsUtils } from "./PopsUtils";
14
13
  import { PopsSafeUtils } from "./PopsSafeUtils";
15
14
 
@@ -32,17 +31,11 @@ class PopsDOMUtilsEvent {
32
31
  * console.log("事件触发",event)
33
32
  * })
34
33
  */
35
- on(
36
- element: PopsDOMUtilsElementEventType,
37
- eventType: string | string[],
38
- callback: (event: Event) => void,
39
- option?: boolean | AddEventListenerOptions
40
- ): void;
41
34
  on<T extends PopsDOMUtils_EventType>(
42
35
  element: PopsDOMUtilsElementEventType,
43
36
  eventType: T | T[],
44
- callback: (event: PopsDOMUtils_Event[T]) => void,
45
- option?: boolean | AddEventListenerOptions
37
+ callback: (this: HTMLElement, event: PopsDOMUtils_Event[T]) => void,
38
+ option?: PopsDOMUtilsEventListenerOption | boolean
46
39
  ): void;
47
40
  /**
48
41
  * 绑定事件
@@ -64,9 +57,9 @@ class PopsDOMUtilsEvent {
64
57
  */
65
58
  on<T extends Event>(
66
59
  element: PopsDOMUtilsElementEventType,
67
- eventType: string,
68
- callback: (event: T) => void,
69
- option?: boolean | AddEventListenerOptions
60
+ eventType: string | string[],
61
+ callback: (this: HTMLElement, event: T) => void,
62
+ option?: PopsDOMUtilsEventListenerOption | boolean
70
63
  ): void;
71
64
  /**
72
65
  * 绑定事件
@@ -80,31 +73,28 @@ class PopsDOMUtilsEvent {
80
73
  * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
81
74
  * @example
82
75
  * // 监听元素a.xx的click、tap、hover事件
83
- * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event)=>{
84
- * console.log("事件触发",event)
76
+ * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event, selectorTarget)=>{
77
+ * console.log("事件触发", event, selectorTarget)
85
78
  * })
86
- * DOMUtils.on("a.xx",["click","tap","hover"],(event)=>{
87
- * console.log("事件触发",event)
79
+ * DOMUtils.on("a.xx",["click","tap","hover"],(event, selectorTarget)=>{
80
+ * console.log("事件触发", event, selectorTarget)
88
81
  * })
89
82
  * @example
90
83
  * // 监听全局document下的子元素a.xx的click事件
91
- * DOMUtils.on(document,"click tap hover","a.xx",(event)=>{
92
- * console.log("事件触发",event)
84
+ * DOMUtils.on(document,"click tap hover","a.xx",(event, selectorTarget)=>{
85
+ * console.log("事件触发", event, selectorTarget)
93
86
  * })
94
87
  */
95
88
  on<T extends PopsDOMUtils_EventType>(
96
89
  element: PopsDOMUtilsElementEventType,
97
90
  eventType: T | T[],
98
- selector: string | undefined | null,
99
- callback: (event: PopsDOMUtils_Event[T]) => void,
100
- option?: boolean | AddEventListenerOptions
101
- ): void;
102
- on<T extends Event>(
103
- element: PopsDOMUtilsElementEventType,
104
- eventType: string | string[],
105
- selector: string | undefined | null,
106
- callback: (event: T) => void,
107
- option?: boolean | AddEventListenerOptions
91
+ selector: string | string[] | undefined | null,
92
+ callback: (
93
+ this: HTMLElement,
94
+ event: PopsDOMUtils_Event[T],
95
+ selectorTarget: HTMLElement
96
+ ) => void,
97
+ option?: PopsDOMUtilsEventListenerOption | boolean
108
98
  ): void;
109
99
  /**
110
100
  * 绑定事件
@@ -118,24 +108,28 @@ class PopsDOMUtilsEvent {
118
108
  * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
119
109
  * @example
120
110
  * // 监听元素a.xx的click、tap、hover事件
121
- * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event)=>{
122
- * console.log("事件触发",event)
111
+ * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event, selectorTarget)=>{
112
+ * console.log("事件触发", event, selectorTarget)
123
113
  * })
124
- * DOMUtils.on("a.xx",["click","tap","hover"],(event)=>{
125
- * console.log("事件触发",event)
114
+ * DOMUtils.on("a.xx",["click","tap","hover"],(event, selectorTarget)=>{
115
+ * console.log("事件触发", event, selectorTarget)
126
116
  * })
127
117
  * @example
128
118
  * // 监听全局document下的子元素a.xx的click事件
129
- * DOMUtils.on(document,"click tap hover","a.xx",(event)=>{
130
- * console.log("事件触发",event)
119
+ * DOMUtils.on(document,"click tap hover","a.xx",(event, selectorTarget)=>{
120
+ * console.log("事件触发", event, selectorTarget)
131
121
  * })
132
122
  */
133
123
  on<T extends Event>(
134
124
  element: PopsDOMUtilsElementEventType,
135
- eventType: string,
136
- selector: string | undefined | null,
137
- callback: (event: T) => void,
138
- option?: boolean | AddEventListenerOptions
125
+ eventType: string | string[],
126
+ selector: string | string[] | undefined | null,
127
+ callback: (
128
+ this: HTMLElement,
129
+ event: T,
130
+ selectorTarget: HTMLElement
131
+ ) => void,
132
+ option?: PopsDOMUtilsEventListenerOption | boolean
139
133
  ): void;
140
134
  on<T extends Event>(
141
135
  element:
@@ -148,10 +142,22 @@ class PopsDOMUtilsEvent {
148
142
  | Element
149
143
  | null
150
144
  | typeof globalThis,
151
- eventType: PopsDOMUtils_EventType | PopsDOMUtils_EventType[] | string,
152
- selector: string | undefined | ((event: T) => void) | null,
153
- callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
154
- option?: boolean | AddEventListenerOptions
145
+ eventType:
146
+ | PopsDOMUtils_EventType
147
+ | PopsDOMUtils_EventType[]
148
+ | string
149
+ | string[],
150
+ selector:
151
+ | string
152
+ | string[]
153
+ | undefined
154
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
155
+ | null,
156
+ callback?:
157
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
158
+ | PopsDOMUtilsEventListenerOption
159
+ | boolean,
160
+ option?: PopsDOMUtilsEventListenerOption | boolean
155
161
  ) {
156
162
  /**
157
163
  * 获取option配置
@@ -162,10 +168,11 @@ class PopsDOMUtilsEvent {
162
168
  function getOption(
163
169
  args: IArguments,
164
170
  startIndex: number,
165
- option: AddEventListenerOptions
171
+ option: PopsDOMUtilsEventListenerOption
166
172
  ) {
167
- if (typeof args[startIndex] === "boolean") {
168
- option.capture = args[startIndex];
173
+ let currentParam = args[startIndex];
174
+ if (typeof currentParam === "boolean") {
175
+ option.capture = currentParam;
169
176
  if (typeof args[startIndex + 1] === "boolean") {
170
177
  option.once = args[startIndex + 1];
171
178
  }
@@ -173,14 +180,16 @@ class PopsDOMUtilsEvent {
173
180
  option.passive = args[startIndex + 2];
174
181
  }
175
182
  } else if (
176
- typeof args[startIndex] === "object" &&
177
- ("capture" in args[startIndex] ||
178
- "once" in args[startIndex] ||
179
- "passive" in args[startIndex])
183
+ typeof currentParam === "object" &&
184
+ ("capture" in currentParam ||
185
+ "once" in currentParam ||
186
+ "passive" in currentParam ||
187
+ "isComposedPath" in currentParam)
180
188
  ) {
181
- option.capture = args[startIndex].capture;
182
- option.once = args[startIndex].once;
183
- option.passive = args[startIndex].passive;
189
+ option.capture = currentParam.capture;
190
+ option.once = currentParam.once;
191
+ option.passive = currentParam.passive;
192
+ option.isComposedPath = currentParam.isComposedPath;
184
193
  }
185
194
  return option;
186
195
  }
@@ -188,7 +197,7 @@ class PopsDOMUtilsEvent {
188
197
  let DOMUtilsContext = this;
189
198
  let args = arguments;
190
199
  if (typeof element === "string") {
191
- element = PopsCore.document.querySelectorAll(element);
200
+ element = DOMUtilsContext.selectorAll(element);
192
201
  }
193
202
  if (element == null) {
194
203
  return;
@@ -200,34 +209,59 @@ class PopsDOMUtilsEvent {
200
209
  } else {
201
210
  elementList.push(element as HTMLElement);
202
211
  }
203
-
212
+ // 事件名
204
213
  let eventTypeList: string[] = [];
205
214
  if (Array.isArray(eventType)) {
206
- eventTypeList = eventTypeList.concat(eventType as string[]);
215
+ eventTypeList = eventTypeList.concat(
216
+ eventType.filter(
217
+ (eventTypeItem) =>
218
+ typeof eventTypeItem === "string" && eventTypeItem.toString() !== ""
219
+ )
220
+ );
207
221
  } else if (typeof eventType === "string") {
208
- eventTypeList = eventTypeList.concat(eventType.split(" "));
222
+ eventTypeList = eventTypeList.concat(
223
+ eventType.split(" ").filter((eventTypeItem) => eventTypeItem !== "")
224
+ );
209
225
  }
210
- let _selector_: string | undefined = selector as any;
211
- let _callback_: (event: T) => void = callback as any;
212
- let _option_: AddEventListenerOptions = {
226
+ // 子元素选择器
227
+ let selectorList: string[] = [];
228
+ if (Array.isArray(selector)) {
229
+ selectorList = selectorList.concat(
230
+ selector.filter(
231
+ (selectorItem) =>
232
+ typeof selectorItem === "string" && selectorItem.toString() !== ""
233
+ )
234
+ );
235
+ } else if (typeof selector === "string") {
236
+ selectorList.push(selector);
237
+ }
238
+ // 事件回调
239
+ let listenerCallBack: (
240
+ this: HTMLElement,
241
+ event: Event,
242
+ selectorTarget?: HTMLElement
243
+ ) => void = callback as any;
244
+ // 事件配置
245
+ let listenerOption: PopsDOMUtilsEventListenerOption = {
213
246
  capture: false,
214
247
  once: false,
215
248
  passive: false,
249
+ isComposedPath: false,
216
250
  };
217
251
  if (typeof selector === "function") {
218
- /* 这是为没有selector的情况 */
219
- _selector_ = void 0;
220
- _callback_ = selector;
221
- _option_ = getOption(args, 3, _option_);
252
+ // 这是为没有selector的情况
253
+ // 那么它就是callback
254
+ listenerCallBack = selector as any;
255
+ listenerOption = getOption(args, 3, listenerOption);
222
256
  } else {
223
- /* 这是存在selector的情况 */
224
- _option_ = getOption(args, 4, _option_);
257
+ // 这是存在selector的情况
258
+ listenerOption = getOption(args, 4, listenerOption);
225
259
  }
226
260
  /**
227
261
  * 如果是once,那么删除该监听和元素上的事件和监听
228
262
  */
229
263
  function checkOptionOnceToRemoveEventListener() {
230
- if (_option_.once) {
264
+ if (listenerOption.once) {
231
265
  DOMUtilsContext.off(
232
266
  element,
233
267
  eventType as any,
@@ -238,57 +272,80 @@ class PopsDOMUtilsEvent {
238
272
  }
239
273
  }
240
274
  elementList.forEach((elementItem) => {
241
- function ownCallBack(event: Event) {
242
- let target = event.target as HTMLElement;
243
- if (_selector_) {
244
- /* 存在自定义子元素选择器 */
245
- let totalParent = popsUtils.isWin(elementItem)
246
- ? PopsCore.document.documentElement
247
- : elementItem;
248
- if (target.matches(_selector_)) {
249
- /* 当前目标可以被selector所匹配到 */
250
- _callback_.call(target, event as any);
251
- checkOptionOnceToRemoveEventListener();
252
- } else if (
253
- target.closest(_selector_) &&
254
- totalParent.contains(target.closest(_selector_))
255
- ) {
275
+ /**
276
+ * 事件回调
277
+ * @param event
278
+ */
279
+ function domUtilsEventCallBack(event: Event) {
280
+ if (selectorList.length) {
281
+ /* 存在子元素选择器 */
282
+ // 这时候的this和target都是子元素选择器的元素
283
+ let eventTarget = listenerOption.isComposedPath
284
+ ? (event.composedPath()[0] as HTMLElement)
285
+ : (event.target as HTMLElement);
286
+ let totalParent = elementItem;
287
+ if (popsUtils.isWin(totalParent)) {
288
+ if (totalParent === (PopsCore.document as any as HTMLElement)) {
289
+ totalParent = PopsCore.document.documentElement;
290
+ }
291
+ }
292
+ let findValue = selectorList.find((selectorItem) => {
293
+ // 判断目标元素是否匹配选择器
294
+ if (DOMUtilsContext.matches(eventTarget, selectorItem)) {
295
+ /* 当前目标可以被selector所匹配到 */
296
+ return true;
297
+ }
256
298
  /* 在上层与主元素之间寻找可以被selector所匹配到的 */
257
- let closestElement = target.closest(_selector_);
258
- /* event的target值不能直接修改 */
259
- OriginPrototype.Object.defineProperty(event, "target", {
260
- get() {
261
- return closestElement;
262
- },
263
- });
264
- _callback_.call(closestElement, event as any);
299
+ let $closestMatches = DOMUtilsContext.closest<HTMLElement>(
300
+ eventTarget,
301
+ selectorItem
302
+ );
303
+ if ($closestMatches && totalParent?.contains($closestMatches)) {
304
+ eventTarget = $closestMatches;
305
+ return true;
306
+ }
307
+ return false;
308
+ });
309
+ if (findValue) {
310
+ // 这里尝试使用defineProperty修改event的target值
311
+ try {
312
+ OriginPrototype.Object.defineProperty(event, "target", {
313
+ get() {
314
+ return eventTarget;
315
+ },
316
+ });
317
+ } catch (error) {}
318
+ listenerCallBack.call(eventTarget, event as any, eventTarget);
265
319
  checkOptionOnceToRemoveEventListener();
266
320
  }
267
321
  } else {
268
- _callback_.call(elementItem, event as any);
322
+ // 这时候的this指向监听的元素
323
+ listenerCallBack.call(elementItem, event as any);
269
324
  checkOptionOnceToRemoveEventListener();
270
325
  }
271
326
  }
272
327
 
273
328
  /* 遍历事件名设置元素事件 */
274
329
  eventTypeList.forEach((eventName) => {
275
- elementItem.addEventListener(eventName, ownCallBack, _option_);
276
-
277
- if (_callback_ && (_callback_ as any).delegate) {
278
- elementItem.setAttribute("data-delegate", _selector_ as string);
279
- }
330
+ elementItem.addEventListener(
331
+ eventName,
332
+ domUtilsEventCallBack,
333
+ listenerOption
334
+ );
280
335
  /* 获取对象上的事件 */
281
- let elementEvents = (elementItem as any)[SymbolEvents] || {};
336
+ let elementEvents: {
337
+ [k: string]: PopsDOMUtilsEventListenerOptionsAttribute[];
338
+ } = Reflect.get(elementItem, SymbolEvents) || {};
282
339
  /* 初始化对象上的xx事件 */
283
340
  elementEvents[eventName] = elementEvents[eventName] || [];
284
341
  elementEvents[eventName].push({
285
- selector: _selector_,
286
- option: _option_,
287
- callback: ownCallBack,
288
- originCallBack: _callback_,
342
+ selector: selectorList,
343
+ option: listenerOption,
344
+ callback: domUtilsEventCallBack,
345
+ originCallBack: listenerCallBack,
289
346
  });
290
347
  /* 覆盖事件 */
291
- (elementItem as any)[SymbolEvents] = elementEvents;
348
+ Reflect.set(elementItem, SymbolEvents, elementEvents);
292
349
  });
293
350
  });
294
351
  }
@@ -301,26 +358,15 @@ class PopsDOMUtilsEvent {
301
358
  * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
302
359
  * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
303
360
  * @example
304
- * // 取消监听元素a.xxclick事件
361
+ * // 取消监听元素a.xx所有的click事件
305
362
  * DOMUtils.off(document.querySelector("a.xx"),"click")
306
363
  * DOMUtils.off("a.xx","click")
307
364
  */
308
- off(
309
- element: PopsDOMUtilsElementEventType,
310
- eventType: string | string[],
311
- callback?: (event: Event) => void,
312
- option?: boolean | AddEventListenerOptions,
313
- filter?: (
314
- value: PopsDOMUtilsEventListenerOptionsAttribute,
315
- index: number,
316
- array: PopsDOMUtilsEventListenerOptionsAttribute[]
317
- ) => boolean
318
- ): void;
319
365
  off<T extends PopsDOMUtils_EventType>(
320
366
  element: PopsDOMUtilsElementEventType,
321
367
  eventType: T | T[],
322
- callback?: (event: PopsDOMUtils_Event[T]) => void,
323
- option?: boolean | AddEventListenerOptions,
368
+ callback?: (this: HTMLElement, event: PopsDOMUtils_Event[T]) => void,
369
+ option?: EventListenerOptions | boolean,
324
370
  filter?: (
325
371
  value: PopsDOMUtilsEventListenerOptionsAttribute,
326
372
  index: number,
@@ -342,9 +388,9 @@ class PopsDOMUtilsEvent {
342
388
  */
343
389
  off<T extends Event>(
344
390
  element: PopsDOMUtilsElementEventType,
345
- eventType: string,
346
- callback?: (event: T) => void,
347
- option?: boolean | AddEventListenerOptions,
391
+ eventType: string | string[],
392
+ callback?: (this: HTMLElement, event: T) => void,
393
+ option?: EventListenerOptions | boolean,
348
394
  filter?: (
349
395
  value: PopsDOMUtilsEventListenerOptionsAttribute,
350
396
  index: number,
@@ -368,9 +414,13 @@ class PopsDOMUtilsEvent {
368
414
  off<T extends PopsDOMUtils_EventType>(
369
415
  element: PopsDOMUtilsElementEventType,
370
416
  eventType: T | T[],
371
- selector?: string | undefined,
372
- callback?: (event: PopsDOMUtils_Event[T]) => void,
373
- option?: boolean | AddEventListenerOptions,
417
+ selector?: string | string[] | undefined | null,
418
+ callback?: (
419
+ this: HTMLElement,
420
+ event: PopsDOMUtils_Event[T],
421
+ selectorTarget: HTMLElement
422
+ ) => void,
423
+ option?: EventListenerOptions | boolean,
374
424
  filter?: (
375
425
  value: PopsDOMUtilsEventListenerOptionsAttribute,
376
426
  index: number,
@@ -394,9 +444,13 @@ class PopsDOMUtilsEvent {
394
444
  off<T extends Event>(
395
445
  element: PopsDOMUtilsElementEventType,
396
446
  eventType: string | string[],
397
- selector?: string | undefined,
398
- callback?: (event: T) => void,
399
- option?: boolean | AddEventListenerOptions,
447
+ selector?: string | string[] | undefined | null,
448
+ callback?: (
449
+ this: HTMLElement,
450
+ event: T,
451
+ selectorTarget: HTMLElement
452
+ ) => void,
453
+ option?: EventListenerOptions | boolean,
400
454
  filter?: (
401
455
  value: PopsDOMUtilsEventListenerOptionsAttribute,
402
456
  index: number,
@@ -419,11 +473,19 @@ class PopsDOMUtilsEvent {
419
473
  | PopsDOMUtils_EventType[]
420
474
  | string
421
475
  | string[],
422
- selector?: string | undefined | ((event: T) => void),
423
- callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
476
+ selector:
477
+ | string
478
+ | string[]
479
+ | undefined
480
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
481
+ | null,
482
+ callback?:
483
+ | ((this: HTMLElement, event: T, selectorTarget: HTMLElement) => void)
484
+ | EventListenerOptions
485
+ | boolean,
424
486
  option?:
487
+ | EventListenerOptions
425
488
  | boolean
426
- | AddEventListenerOptions
427
489
  | ((
428
490
  value: PopsDOMUtilsEventListenerOptionsAttribute,
429
491
  index: number,
@@ -446,20 +508,21 @@ class PopsDOMUtilsEvent {
446
508
  startIndex: number,
447
509
  option: EventListenerOptions
448
510
  ) {
449
- if (typeof args1[startIndex] === "boolean") {
450
- option.capture = args1[startIndex];
511
+ let currentParam: EventListenerOptions | boolean = args1[startIndex];
512
+ if (typeof currentParam === "boolean") {
513
+ option.capture = currentParam;
451
514
  } else if (
452
- typeof args1[startIndex] === "object" &&
453
- "capture" in args1[startIndex]
515
+ typeof currentParam === "object" &&
516
+ "capture" in currentParam
454
517
  ) {
455
- option.capture = args1[startIndex].capture;
518
+ option.capture = currentParam.capture;
456
519
  }
457
520
  return option;
458
521
  }
459
-
522
+ let DOMUtilsContext = this;
460
523
  let args = arguments;
461
524
  if (typeof element === "string") {
462
- element = PopsCore.document.querySelectorAll(element);
525
+ element = DOMUtilsContext.selectorAll(element);
463
526
  }
464
527
  if (element == null) {
465
528
  return;
@@ -473,63 +536,103 @@ class PopsDOMUtilsEvent {
473
536
  }
474
537
  let eventTypeList: string[] = [];
475
538
  if (Array.isArray(eventType)) {
476
- eventTypeList = eventTypeList.concat(eventType as string[]);
539
+ eventTypeList = eventTypeList.concat(
540
+ eventType.filter(
541
+ (eventTypeItem) =>
542
+ typeof eventTypeItem === "string" && eventTypeItem.toString() !== ""
543
+ )
544
+ );
477
545
  } else if (typeof eventType === "string") {
478
- eventTypeList = eventTypeList.concat(eventType.split(" "));
546
+ eventTypeList = eventTypeList.concat(
547
+ eventType.split(" ").filter((eventTypeItem) => eventTypeItem !== "")
548
+ );
549
+ }
550
+ // 子元素选择器
551
+ let selectorList: string[] = [];
552
+ if (Array.isArray(selector)) {
553
+ selectorList = selectorList.concat(
554
+ selector.filter(
555
+ (selectorItem) =>
556
+ typeof selectorItem === "string" && selectorItem.toString() !== ""
557
+ )
558
+ );
559
+ } else if (typeof selector === "string") {
560
+ selectorList.push(selector);
479
561
  }
480
- /**
481
- * 子元素选择器
482
- */
483
- let _selector_: string | undefined = selector as any;
484
562
  /**
485
563
  * 事件的回调函数
486
564
  */
487
- let _callback_: (event: T) => void = callback as any;
565
+ let listenerCallBack: (
566
+ this: HTMLElement,
567
+ event: T,
568
+ selectorTarget: HTMLElement
569
+ ) => void = callback as any;
488
570
 
489
571
  /**
490
572
  * 事件的配置
491
573
  */
492
- let _option_: EventListenerOptions = {
574
+ let listenerOption: EventListenerOptions = {
493
575
  capture: false,
494
576
  };
495
577
  if (typeof selector === "function") {
496
- /* 这是为没有selector的情况 */
497
- _selector_ = void 0;
498
- _callback_ = selector;
499
- _option_ = getOption(args, 3, _option_);
578
+ // 这是为没有selector的情况
579
+ // 那么它就是callback
580
+ listenerCallBack = selector;
581
+ listenerOption = getOption(args, 3, listenerOption);
500
582
  } else {
501
- _option_ = getOption(args, 4, _option_);
583
+ // 这是存在selector的情况
584
+ listenerOption = getOption(args, 4, listenerOption);
585
+ }
586
+ // 是否移除所有事件
587
+ let isRemoveAll = false;
588
+ if (args.length === 2) {
589
+ // 目标函数、事件名
590
+ isRemoveAll = true;
591
+ } else if (
592
+ (args.length === 3 && typeof args[2] === "string") ||
593
+ Array.isArray(args[2])
594
+ ) {
595
+ // 目标函数、事件名、子元素选择器
596
+ isRemoveAll = true;
502
597
  }
503
598
  elementList.forEach((elementItem) => {
504
599
  /* 获取对象上的事件 */
505
- let elementEvents = (elementItem as any)[SymbolEvents] || {};
600
+ let elementEvents: {
601
+ [key: string]: PopsDOMUtilsEventListenerOptionsAttribute[];
602
+ } = Reflect.get(elementItem, SymbolEvents) || {};
506
603
  eventTypeList.forEach((eventName) => {
507
- let handlers: PopsDOMUtilsEventListenerOptionsAttribute[] =
508
- elementEvents[eventName] || [];
604
+ let handlers = elementEvents[eventName] || [];
509
605
  if (typeof filter === "function") {
510
606
  handlers = handlers.filter(filter);
511
607
  }
512
608
  for (let index = 0; index < handlers.length; index++) {
513
609
  let handler = handlers[index];
514
- let flag = false;
515
- if (!_selector_ || handler.selector === _selector_) {
516
- /* selector不为空,进行selector判断 */
517
- flag = true;
518
- }
610
+ let flag = true;
519
611
  if (
520
- !_callback_ ||
521
- handler.callback === _callback_ ||
522
- handler.originCallBack === _callback_
612
+ flag &&
613
+ listenerCallBack &&
614
+ handler.originCallBack !== listenerCallBack
523
615
  ) {
524
- /* callback不为空,进行callback判断 */
525
- flag = true;
616
+ // callback不同
617
+ flag = false;
526
618
  }
527
-
528
- if (flag) {
619
+ if (flag && selectorList.length && Array.isArray(handler.selector)) {
620
+ if (
621
+ JSON.stringify(handler.selector) !== JSON.stringify(selectorList)
622
+ ) {
623
+ // 子元素选择器不同
624
+ flag = false;
625
+ }
626
+ }
627
+ if (flag && listenerOption.capture !== handler.option.capture) {
628
+ // 事件的配置项不同
629
+ flag = false;
630
+ }
631
+ if (flag || isRemoveAll) {
529
632
  elementItem.removeEventListener(
530
633
  eventName,
531
634
  handler.callback,
532
- _option_
635
+ handler.option
533
636
  );
534
637
  handlers.splice(index--, 1);
535
638
  }
@@ -539,7 +642,7 @@ class PopsDOMUtilsEvent {
539
642
  popsUtils.delete(elementEvents, eventType);
540
643
  }
541
644
  });
542
- (elementItem as any)[SymbolEvents] = elementEvents;
645
+ Reflect.set(elementItem, SymbolEvents, elementEvents);
543
646
  });
544
647
  }
545
648
  /**
@@ -1083,6 +1186,268 @@ class PopsDOMUtilsEvent {
1083
1186
  });
1084
1187
  }
1085
1188
  }
1189
+ /**
1190
+ * 选择器,可使用以下的额外语法
1191
+ *
1192
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1193
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1194
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1195
+ * @param selector 选择器
1196
+ * @example
1197
+ * DOMUtils.selector("div:contains('测试')")
1198
+ * > div.xxx
1199
+ * @example
1200
+ * DOMUtils.selector("div:empty")
1201
+ * > div.xxx
1202
+ * @example
1203
+ * DOMUtils.selector("div:regexp('^xxxx$')")
1204
+ * > div.xxx
1205
+ */
1206
+ selector<K extends keyof HTMLElementTagNameMap>(
1207
+ selector: K
1208
+ ): HTMLElementTagNameMap[K] | undefined;
1209
+ selector<E extends Element = Element>(selector: string): E | undefined;
1210
+ selector<E extends Element = Element>(selector: string) {
1211
+ return this.selectorAll<E>(selector)[0];
1212
+ }
1213
+ /**
1214
+ * 选择器,可使用以下的额外语法
1215
+ *
1216
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1217
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1218
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1219
+ * @param selector 选择器
1220
+ * @example
1221
+ * DOMUtils.selectorAll("div:contains('测试')")
1222
+ * > [div.xxx]
1223
+ * @example
1224
+ * DOMUtils.selectorAll("div:empty")
1225
+ * > [div.xxx]
1226
+ * @example
1227
+ * DOMUtils.selectorAll("div:regexp('^xxxx$')")
1228
+ * > [div.xxx]
1229
+ * @example
1230
+ * DOMUtils.selectorAll("div:regexp(/^xxx/ig)")
1231
+ * > [div.xxx]
1232
+ */
1233
+ selectorAll<K extends keyof HTMLElementTagNameMap>(
1234
+ selector: K
1235
+ ): HTMLElementTagNameMap[K][];
1236
+ selectorAll<E extends Element = Element>(selector: string): E[];
1237
+ selectorAll<E extends Element = Element>(selector: string) {
1238
+ selector = selector.trim();
1239
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1240
+ // empty 语法
1241
+ selector = selector.replace(/:empty$/gi, "");
1242
+ return Array.from(PopsCore.document.querySelectorAll<E>(selector)).filter(
1243
+ ($ele) => {
1244
+ return $ele?.innerHTML?.trim() === "";
1245
+ }
1246
+ );
1247
+ } else if (
1248
+ selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
1249
+ selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
1250
+ ) {
1251
+ // contains 语法
1252
+ let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1253
+ let text = textMatch![2];
1254
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1255
+ return Array.from(PopsCore.document.querySelectorAll<E>(selector)).filter(
1256
+ ($ele) => {
1257
+ // @ts-ignore
1258
+ return ($ele?.textContent || $ele?.innerText)?.includes(text);
1259
+ }
1260
+ );
1261
+ } else if (
1262
+ selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
1263
+ selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
1264
+ ) {
1265
+ // regexp 语法
1266
+ let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1267
+ let pattern = textMatch![2];
1268
+ let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1269
+ let flags = "";
1270
+ if (flagMatch) {
1271
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1272
+ flags = flagMatch[3];
1273
+ }
1274
+ let regexp = new RegExp(pattern, flags);
1275
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1276
+ return Array.from(PopsCore.document.querySelectorAll<E>(selector)).filter(
1277
+ ($ele) => {
1278
+ // @ts-ignore
1279
+ return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
1280
+ }
1281
+ );
1282
+ } else {
1283
+ // 普通语法
1284
+ return Array.from(PopsCore.document.querySelectorAll<E>(selector));
1285
+ }
1286
+ }
1287
+ /**
1288
+ * 匹配元素,可使用以下的额外语法
1289
+ *
1290
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1291
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1292
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1293
+ * @param $el 元素
1294
+ * @param selector 选择器
1295
+ * @example
1296
+ * DOMUtils.matches("div:contains('测试')")
1297
+ * > true
1298
+ * @example
1299
+ * DOMUtils.matches("div:empty")
1300
+ * > true
1301
+ * @example
1302
+ * DOMUtils.matches("div:regexp('^xxxx$')")
1303
+ * > true
1304
+ * @example
1305
+ * DOMUtils.matches("div:regexp(/^xxx/ig)")
1306
+ * > false
1307
+ */
1308
+ matches(
1309
+ $el: HTMLElement | Element | null | undefined,
1310
+ selector: string
1311
+ ): boolean {
1312
+ selector = selector.trim();
1313
+ if ($el == null) {
1314
+ return false;
1315
+ }
1316
+
1317
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1318
+ // empty 语法
1319
+ selector = selector.replace(/:empty$/gi, "");
1320
+ return $el.matches(selector) && $el?.innerHTML?.trim() === "";
1321
+ } else if (
1322
+ selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
1323
+ selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
1324
+ ) {
1325
+ // contains 语法
1326
+ let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1327
+ let text = textMatch![2];
1328
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1329
+ // @ts-ignore
1330
+ let content = $el?.textContent || $el?.innerText;
1331
+ if (typeof content !== "string") {
1332
+ content = "";
1333
+ }
1334
+ return $el.matches(selector) && content?.includes(text);
1335
+ } else if (
1336
+ selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
1337
+ selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
1338
+ ) {
1339
+ // regexp 语法
1340
+ let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1341
+ let pattern = textMatch![2];
1342
+ let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1343
+ let flags = "";
1344
+ if (flagMatch) {
1345
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1346
+ flags = flagMatch[3];
1347
+ }
1348
+ let regexp = new RegExp(pattern, flags);
1349
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1350
+ // @ts-ignore
1351
+ let content = $el?.textContent || $el?.innerText;
1352
+ if (typeof content !== "string") {
1353
+ content = "";
1354
+ }
1355
+ return $el.matches(selector) && Boolean(content?.match(regexp));
1356
+ } else {
1357
+ // 普通语法
1358
+ return $el.matches(selector);
1359
+ }
1360
+ }
1361
+ /**
1362
+ * 根据选择器获取上层元素,可使用以下的额外语法
1363
+ *
1364
+ * + :contains([text]) 作用: 找到包含指定文本内容的指定元素
1365
+ * + :empty 作用:找到既没有文本内容也没有子元素的指定元素
1366
+ * + :regexp([text]) 作用: 找到符合正则表达式的内容的指定元素
1367
+ * @param $el 元素
1368
+ * @param selector 选择器
1369
+ * @example
1370
+ * DOMUtils.closest("div:contains('测试')")
1371
+ * > div.xxx
1372
+ * @example
1373
+ * DOMUtils.closest("div:empty")
1374
+ * > div.xxx
1375
+ * @example
1376
+ * DOMUtils.closest("div:regexp('^xxxx$')")
1377
+ * > div.xxxx
1378
+ * @example
1379
+ * DOMUtils.closest("div:regexp(/^xxx/ig)")
1380
+ * > null
1381
+ */
1382
+ closest<K extends keyof HTMLElementTagNameMap>(
1383
+ $el: HTMLElement | Element,
1384
+ selector: string
1385
+ ): HTMLElementTagNameMap[K] | null;
1386
+ closest<E extends Element = Element>(
1387
+ $el: HTMLElement | Element,
1388
+ selector: string
1389
+ ): E | null;
1390
+ closest<E extends Element = Element>(
1391
+ $el: HTMLElement | Element,
1392
+ selector: string
1393
+ ): E | null {
1394
+ selector = selector.trim();
1395
+
1396
+ if (selector.match(/[^\s]{1}:empty$/gi)) {
1397
+ // empty 语法
1398
+ selector = selector.replace(/:empty$/gi, "");
1399
+ let $closest = $el?.closest<E>(selector);
1400
+ if ($closest && $closest?.innerHTML?.trim() === "") {
1401
+ return $closest;
1402
+ }
1403
+ return null;
1404
+ } else if (
1405
+ selector.match(/[^\s]{1}:contains\("(.*)"\)$/i) ||
1406
+ selector.match(/[^\s]{1}:contains\('(.*)'\)$/i)
1407
+ ) {
1408
+ // contains 语法
1409
+ let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1410
+ let text = textMatch![2];
1411
+ selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1412
+ let $closest = $el?.closest<E>(selector);
1413
+ if ($closest) {
1414
+ // @ts-ignore
1415
+ let content = $el?.textContent || $el?.innerText;
1416
+ if (typeof content === "string" && content.includes(text)) {
1417
+ return $closest;
1418
+ }
1419
+ }
1420
+ return null;
1421
+ } else if (
1422
+ selector.match(/[^\s]{1}:regexp\("(.*)"\)$/i) ||
1423
+ selector.match(/[^\s]{1}:regexp\('(.*)'\)$/i)
1424
+ ) {
1425
+ // regexp 语法
1426
+ let textMatch = selector.match(/:regexp\(("|')(.*)("|')\)$/i);
1427
+ let pattern = textMatch![2];
1428
+ let flagMatch = pattern.match(/("|'),[\s]*("|')([igm]{0,3})$/i);
1429
+ let flags = "";
1430
+ if (flagMatch) {
1431
+ pattern = pattern.replace(/("|'),[\s]*("|')([igm]{0,3})$/gi, "");
1432
+ flags = flagMatch[3];
1433
+ }
1434
+ let regexp = new RegExp(pattern, flags);
1435
+ selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1436
+ let $closest = $el?.closest<E>(selector);
1437
+ if ($closest) {
1438
+ // @ts-ignore
1439
+ let content = $el?.textContent || $el?.innerText;
1440
+ if (typeof content === "string" && content.match(regexp)) {
1441
+ return $closest;
1442
+ }
1443
+ }
1444
+ return null;
1445
+ } else {
1446
+ // 普通语法
1447
+ let $closest = $el?.closest<E>(selector);
1448
+ return $closest;
1449
+ }
1450
+ }
1086
1451
  }
1087
1452
 
1088
1453
  class PopsDOMUtils extends PopsDOMUtilsEvent {