@whitesev/domutils 1.4.3 → 1.4.5

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.
@@ -6,6 +6,7 @@ import type {
6
6
  DOMUtils_Event,
7
7
  DOMUtils_EventType,
8
8
  DOMUtilsElementEventType,
9
+ DOMUtilsEventListenerOption,
9
10
  DOMUtilsEventListenerOptionsAttribute,
10
11
  } from "./types/DOMUtilsEvent";
11
12
  import type { DOMUtilsTargetElementType } from "./types/global";
@@ -38,8 +39,8 @@ export class DOMUtilsEvent {
38
39
  on<T extends DOMUtils_EventType>(
39
40
  element: DOMUtilsElementEventType,
40
41
  eventType: T | T[],
41
- callback: (event: DOMUtils_Event[T]) => void,
42
- option?: boolean | AddEventListenerOptions
42
+ callback: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
43
+ option?: DOMUtilsEventListenerOption | boolean
43
44
  ): void;
44
45
  /**
45
46
  * 绑定事件
@@ -62,8 +63,8 @@ export class DOMUtilsEvent {
62
63
  on<T extends Event>(
63
64
  element: DOMUtilsElementEventType,
64
65
  eventType: string,
65
- callback: (event: T) => void,
66
- option?: boolean | AddEventListenerOptions
66
+ callback: (this: HTMLElement, event: T) => void,
67
+ option?: DOMUtilsEventListenerOption | boolean
67
68
  ): void;
68
69
  /**
69
70
  * 绑定事件
@@ -93,8 +94,8 @@ export class DOMUtilsEvent {
93
94
  element: DOMUtilsElementEventType,
94
95
  eventType: T | T[],
95
96
  selector: string | string[] | undefined | null,
96
- callback: (event: DOMUtils_Event[T]) => void,
97
- option?: boolean | AddEventListenerOptions
97
+ callback: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
98
+ option?: DOMUtilsEventListenerOption | boolean
98
99
  ): void;
99
100
  /**
100
101
  * 绑定事件
@@ -124,8 +125,8 @@ export class DOMUtilsEvent {
124
125
  element: DOMUtilsElementEventType,
125
126
  eventType: string,
126
127
  selector: string | string[] | (() => string | string[]) | undefined | null,
127
- callback: (event: T) => void,
128
- option?: boolean | AddEventListenerOptions
128
+ callback: (this: HTMLElement, event: T) => void,
129
+ option?: DOMUtilsEventListenerOption | boolean
129
130
  ): void;
130
131
  on<T extends Event>(
131
132
  element:
@@ -139,9 +140,17 @@ export class DOMUtilsEvent {
139
140
  | null
140
141
  | typeof globalThis,
141
142
  eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
142
- selector: string | undefined | string[] | ((event: T) => void) | null,
143
- callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
144
- option?: boolean | AddEventListenerOptions
143
+ selector:
144
+ | string
145
+ | undefined
146
+ | string[]
147
+ | ((this: HTMLElement, event: T) => void)
148
+ | null,
149
+ callback?:
150
+ | ((this: HTMLElement, event: T) => void)
151
+ | DOMUtilsEventListenerOption
152
+ | boolean,
153
+ option?: DOMUtilsEventListenerOption | boolean
145
154
  ) {
146
155
  /**
147
156
  * 获取option配置
@@ -152,10 +161,11 @@ export class DOMUtilsEvent {
152
161
  function getOption(
153
162
  args: IArguments,
154
163
  startIndex: number,
155
- option: AddEventListenerOptions
164
+ option: DOMUtilsEventListenerOption
156
165
  ) {
157
- if (typeof args[startIndex] === "boolean") {
158
- option.capture = args[startIndex];
166
+ let currentParam = args[startIndex];
167
+ if (typeof currentParam === "boolean") {
168
+ option.capture = currentParam;
159
169
  if (typeof args[startIndex + 1] === "boolean") {
160
170
  option.once = args[startIndex + 1];
161
171
  }
@@ -163,14 +173,16 @@ export class DOMUtilsEvent {
163
173
  option.passive = args[startIndex + 2];
164
174
  }
165
175
  } else if (
166
- typeof args[startIndex] === "object" &&
167
- ("capture" in args[startIndex] ||
168
- "once" in args[startIndex] ||
169
- "passive" in args[startIndex])
176
+ typeof currentParam === "object" &&
177
+ ("capture" in currentParam ||
178
+ "once" in currentParam ||
179
+ "passive" in currentParam ||
180
+ "isComposedPath" in currentParam)
170
181
  ) {
171
- option.capture = args[startIndex].capture;
172
- option.once = args[startIndex].once;
173
- option.passive = args[startIndex].passive;
182
+ option.capture = currentParam.capture;
183
+ option.once = currentParam.once;
184
+ option.passive = currentParam.passive;
185
+ option.isComposedPath = currentParam.isComposedPath;
174
186
  }
175
187
  return option;
176
188
  }
@@ -205,26 +217,28 @@ export class DOMUtilsEvent {
205
217
  selectorList.push(selector);
206
218
  }
207
219
  // 事件回调
208
- let _callback_: (event: Event) => void = callback as any;
220
+ let listenerCallBack: (this: HTMLElement, event: Event) => void =
221
+ callback as any;
209
222
  // 事件配置
210
- let _option_: AddEventListenerOptions = {
223
+ let listenerOption: DOMUtilsEventListenerOption = {
211
224
  capture: false,
212
225
  once: false,
213
226
  passive: false,
227
+ isComposedPath: false,
214
228
  };
215
229
  if (typeof selector === "function") {
216
230
  /* 这是为没有selector的情况 */
217
- _callback_ = selector as any;
218
- _option_ = getOption(args, 3, _option_);
231
+ listenerCallBack = selector as any;
232
+ listenerOption = getOption(args, 3, listenerOption);
219
233
  } else {
220
234
  /* 这是存在selector的情况 */
221
- _option_ = getOption(args, 4, _option_);
235
+ listenerOption = getOption(args, 4, listenerOption);
222
236
  }
223
237
  /**
224
238
  * 如果是once,那么删除该监听和元素上的事件和监听
225
239
  */
226
240
  function checkOptionOnceToRemoveEventListener() {
227
- if (_option_.once) {
241
+ if (listenerOption.once) {
228
242
  DOMUtilsContext.off(
229
243
  element,
230
244
  eventType as any,
@@ -240,38 +254,44 @@ export class DOMUtilsEvent {
240
254
  * @param event
241
255
  */
242
256
  function domUtilsEventCallBack(event: Event) {
243
- let target = event.target as HTMLElement;
257
+ let eventTarget = listenerOption.isComposedPath
258
+ ? (event.composedPath()[0] as HTMLElement)
259
+ : (event.target as HTMLElement);
244
260
  if (selectorList.length) {
245
- /* 存在自定义子元素选择器 */
261
+ /* 存在子元素选择器 */
246
262
  let totalParent = DOMUtilsCommonUtils.isWin(elementItem)
247
263
  ? DOMUtilsContext.windowApi.document.documentElement
248
264
  : elementItem;
249
265
  for (let index = 0; index < selectorList.length; index++) {
250
266
  const selectorItem = selectorList[index];
251
- if (target.matches(selectorItem)) {
267
+ if (eventTarget.matches(selectorItem)) {
252
268
  /* 当前目标可以被selector所匹配到 */
253
- _callback_.call(target, event as any);
269
+ listenerCallBack.call(eventTarget, event as any);
254
270
  checkOptionOnceToRemoveEventListener();
255
271
  break;
256
- } else if (
257
- target.closest(selectorItem) &&
258
- totalParent.contains(target.closest(selectorItem))
259
- ) {
272
+ } else {
260
273
  /* 在上层与主元素之间寻找可以被selector所匹配到的 */
261
- let closestElement = target.closest(selectorItem);
262
- /* event的target值不能直接修改 */
263
- OriginPrototype.Object.defineProperty(event, "target", {
264
- get() {
265
- return closestElement;
266
- },
267
- });
268
- _callback_.call(closestElement, event as any);
269
- checkOptionOnceToRemoveEventListener();
270
- break;
274
+ let $closestMatches = eventTarget.closest(
275
+ selectorItem
276
+ ) as HTMLElement | null;
277
+ if ($closestMatches && totalParent.contains($closestMatches)) {
278
+ /* event的target值不能直接修改 */
279
+ // 这里尝试使用defineProperty修改event的target值
280
+ try {
281
+ OriginPrototype.Object.defineProperty(event, "target", {
282
+ get() {
283
+ return $closestMatches;
284
+ },
285
+ });
286
+ } catch (error) {}
287
+ listenerCallBack.call($closestMatches, event as any);
288
+ checkOptionOnceToRemoveEventListener();
289
+ break;
290
+ }
271
291
  }
272
292
  }
273
293
  } else {
274
- _callback_.call(elementItem, event as any);
294
+ listenerCallBack.call(elementItem, event as any);
275
295
  checkOptionOnceToRemoveEventListener();
276
296
  }
277
297
  }
@@ -281,7 +301,7 @@ export class DOMUtilsEvent {
281
301
  elementItem.addEventListener(
282
302
  eventName,
283
303
  domUtilsEventCallBack,
284
- _option_
304
+ listenerOption
285
305
  );
286
306
  /* 获取对象上的事件 */
287
307
  let elementEvents: {
@@ -292,9 +312,9 @@ export class DOMUtilsEvent {
292
312
  elementEvents[eventName] = elementEvents[eventName] || [];
293
313
  elementEvents[eventName].push({
294
314
  selector: selectorList,
295
- option: _option_,
315
+ option: listenerOption,
296
316
  callback: domUtilsEventCallBack,
297
- originCallBack: _callback_,
317
+ originCallBack: listenerCallBack,
298
318
  });
299
319
  /* 覆盖事件 */
300
320
  // @ts-ignore
@@ -311,15 +331,15 @@ export class DOMUtilsEvent {
311
331
  * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
312
332
  * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
313
333
  * @example
314
- * // 取消监听元素a.xxclick事件
334
+ * // 取消监听元素a.xx所有的click事件
315
335
  * DOMUtils.off(document.querySelector("a.xx"),"click")
316
336
  * DOMUtils.off("a.xx","click")
317
337
  */
318
338
  off<T extends DOMUtils_EventType>(
319
339
  element: DOMUtilsElementEventType,
320
340
  eventType: T | T[],
321
- callback?: (event: DOMUtils_Event[T]) => void,
322
- option?: boolean | AddEventListenerOptions,
341
+ callback?: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
342
+ option?: boolean | EventListenerOptions,
323
343
  filter?: (
324
344
  value: DOMUtilsEventListenerOptionsAttribute,
325
345
  index: number,
@@ -342,8 +362,8 @@ export class DOMUtilsEvent {
342
362
  off<T extends Event>(
343
363
  element: DOMUtilsElementEventType,
344
364
  eventType: string,
345
- callback?: (event: T) => void,
346
- option?: boolean | AddEventListenerOptions,
365
+ callback?: (this: HTMLElement, event: T) => void,
366
+ option?: boolean | EventListenerOptions,
347
367
  filter?: (
348
368
  value: DOMUtilsEventListenerOptionsAttribute,
349
369
  index: number,
@@ -368,8 +388,8 @@ export class DOMUtilsEvent {
368
388
  element: DOMUtilsElementEventType,
369
389
  eventType: T | T[],
370
390
  selector?: DOMUtilsEventListenerOptionsAttribute["selector"] | undefined,
371
- callback?: (event: DOMUtils_Event[T]) => void,
372
- option?: boolean | AddEventListenerOptions,
391
+ callback?: (this: HTMLElement, event: DOMUtils_Event[T]) => void,
392
+ option?: boolean | EventListenerOptions,
373
393
  filter?: (
374
394
  value: DOMUtilsEventListenerOptionsAttribute,
375
395
  index: number,
@@ -394,8 +414,8 @@ export class DOMUtilsEvent {
394
414
  element: DOMUtilsElementEventType,
395
415
  eventType: string,
396
416
  selector?: DOMUtilsEventListenerOptionsAttribute["selector"] | undefined,
397
- callback?: (event: T) => void,
398
- option?: boolean | AddEventListenerOptions,
417
+ callback?: (this: HTMLElement, event: T) => void,
418
+ option?: boolean | EventListenerOptions,
399
419
  filter?: (
400
420
  value: DOMUtilsEventListenerOptionsAttribute,
401
421
  index: number,
@@ -417,11 +437,14 @@ export class DOMUtilsEvent {
417
437
  selector?:
418
438
  | DOMUtilsEventListenerOptionsAttribute["selector"]
419
439
  | undefined
420
- | ((event: T) => void),
421
- callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
440
+ | ((this: HTMLElement, event: T) => void),
441
+ callback?:
442
+ | ((this: HTMLElement, event: T) => void)
443
+ | boolean
444
+ | EventListenerOptions,
422
445
  option?:
423
446
  | boolean
424
- | AddEventListenerOptions
447
+ | EventListenerOptions
425
448
  | ((
426
449
  value: DOMUtilsEventListenerOptionsAttribute,
427
450
  index: number,
@@ -444,13 +467,14 @@ export class DOMUtilsEvent {
444
467
  startIndex: number,
445
468
  option: EventListenerOptions
446
469
  ) {
447
- if (typeof args1[startIndex] === "boolean") {
448
- option.capture = args1[startIndex];
470
+ let currentParam: boolean | EventListenerOptions = args1[startIndex];
471
+ if (typeof currentParam === "boolean") {
472
+ option.capture = currentParam;
449
473
  } else if (
450
- typeof args1[startIndex] === "object" &&
451
- "capture" in args1[startIndex]
474
+ typeof currentParam === "object" &&
475
+ "capture" in currentParam
452
476
  ) {
453
- option.capture = args1[startIndex].capture;
477
+ option.capture = currentParam.capture;
454
478
  }
455
479
  return option;
456
480
  }
@@ -485,20 +509,33 @@ export class DOMUtilsEvent {
485
509
  /**
486
510
  * 事件的回调函数
487
511
  */
488
- let _callback_: (event: T) => void = callback as any;
512
+ let listenerCallBack: (this: HTMLElement, event: T) => void =
513
+ callback as any;
489
514
 
490
515
  /**
491
516
  * 事件的配置
492
517
  */
493
- let _option_: EventListenerOptions = {
518
+ let listenerOption: EventListenerOptions = {
494
519
  capture: false,
495
520
  };
496
521
  if (typeof selector === "function") {
497
522
  /* 这是为没有selector的情况 */
498
- _callback_ = selector;
499
- _option_ = getOption(args, 3, _option_);
523
+ listenerCallBack = selector;
524
+ listenerOption = getOption(args, 3, listenerOption);
500
525
  } else {
501
- _option_ = getOption(args, 4, _option_);
526
+ listenerOption = getOption(args, 4, listenerOption);
527
+ }
528
+ // 是否移除所有事件
529
+ let isRemoveAll = false;
530
+ if (args.length === 2) {
531
+ // 目标函数、事件名
532
+ isRemoveAll = true;
533
+ } else if (
534
+ (args.length === 3 && typeof args[2] === "string") ||
535
+ Array.isArray(args[2])
536
+ ) {
537
+ // 目标函数、事件名、子元素选择器
538
+ isRemoveAll = true;
502
539
  }
503
540
  elementList.forEach((elementItem) => {
504
541
  /* 获取对象上的事件 */
@@ -512,34 +549,32 @@ export class DOMUtilsEvent {
512
549
  }
513
550
  for (let index = 0; index < handlers.length; index++) {
514
551
  let handler = handlers[index];
515
- let flag = false;
516
- if (!selectorList.length) {
517
- // selectorList是空的,默认移除
518
- flag = true;
519
- } else {
552
+ let flag = true;
553
+ if (
554
+ flag &&
555
+ listenerCallBack &&
556
+ handler.originCallBack !== listenerCallBack
557
+ ) {
558
+ // callback不同
559
+ flag = false;
560
+ }
561
+ if (flag && selectorList.length && Array.isArray(handler.selector)) {
520
562
  if (
521
- Array.isArray(handler.selector) &&
522
- JSON.stringify(handler.selector) === JSON.stringify(selectorList)
563
+ JSON.stringify(handler.selector) !== JSON.stringify(selectorList)
523
564
  ) {
524
- // 元素上的selectorList不为空且和传入的相同
525
- flag = true;
565
+ // 子元素选择器不同
566
+ flag = false;
526
567
  }
527
568
  }
528
-
529
- if (
530
- !_callback_ ||
531
- handler.callback === _callback_ ||
532
- handler.originCallBack === _callback_
533
- ) {
534
- /* callback不为空,且callback相同 */
535
- flag = true;
569
+ if (flag && listenerOption.capture !== handler.option.capture) {
570
+ // 事件的配置项不同
571
+ flag = false;
536
572
  }
537
-
538
- if (flag) {
573
+ if (flag || isRemoveAll) {
539
574
  elementItem.removeEventListener(
540
575
  eventName,
541
576
  handler.callback,
542
- _option_
577
+ handler.option
543
578
  );
544
579
  handlers.splice(index--, 1);
545
580
  }
@@ -830,7 +865,7 @@ export class DOMUtilsEvent {
830
865
  * */
831
866
  click(
832
867
  element: DOMUtilsTargetElementType | typeof globalThis | Window,
833
- handler?: (event: DOMUtils_Event["click"]) => void,
868
+ handler?: (this: HTMLElement, event: DOMUtils_Event["click"]) => void,
834
869
  details?: any,
835
870
  useDispatchToTriggerEvent?: boolean
836
871
  ) {
@@ -880,7 +915,7 @@ export class DOMUtilsEvent {
880
915
  * */
881
916
  blur(
882
917
  element: DOMUtilsTargetElementType | typeof globalThis | Window,
883
- handler?: (event: DOMUtils_Event["blur"]) => void,
918
+ handler?: (this: HTMLElement, event: DOMUtils_Event["blur"]) => void,
884
919
  details?: object,
885
920
  useDispatchToTriggerEvent?: boolean
886
921
  ) {
@@ -935,7 +970,7 @@ export class DOMUtilsEvent {
935
970
  * */
936
971
  focus(
937
972
  element: DOMUtilsTargetElementType | typeof globalThis | Window,
938
- handler?: (event: DOMUtils_Event["focus"]) => void,
973
+ handler?: (this: HTMLElement, event: DOMUtils_Event["focus"]) => void,
939
974
  details?: object,
940
975
  useDispatchToTriggerEvent?: boolean
941
976
  ) {
@@ -985,8 +1020,8 @@ export class DOMUtilsEvent {
985
1020
  */
986
1021
  hover(
987
1022
  element: DOMUtilsTargetElementType,
988
- handler: (event: DOMUtils_Event["hover"]) => void,
989
- option?: boolean | AddEventListenerOptions
1023
+ handler: (this: HTMLElement, event: DOMUtils_Event["hover"]) => void,
1024
+ option?: boolean | DOMUtilsEventListenerOption
990
1025
  ) {
991
1026
  let DOMUtilsContext = this;
992
1027
  if (typeof element === "string") {
@@ -1022,8 +1057,8 @@ export class DOMUtilsEvent {
1022
1057
  */
1023
1058
  keyup(
1024
1059
  element: DOMUtilsTargetElementType | Window | typeof globalThis,
1025
- handler: (event: DOMUtils_Event["keyup"]) => void,
1026
- option?: boolean | AddEventListenerOptions
1060
+ handler: (this: HTMLElement, event: DOMUtils_Event["keyup"]) => void,
1061
+ option?: boolean | DOMUtilsEventListenerOption
1027
1062
  ) {
1028
1063
  let DOMUtilsContext = this;
1029
1064
  if (element == null) {
@@ -1058,8 +1093,8 @@ export class DOMUtilsEvent {
1058
1093
  */
1059
1094
  keydown(
1060
1095
  element: DOMUtilsTargetElementType | Window | typeof globalThis,
1061
- handler: (event: DOMUtils_Event["keydown"]) => void,
1062
- option?: boolean | AddEventListenerOptions
1096
+ handler: (this: HTMLElement, event: DOMUtils_Event["keydown"]) => void,
1097
+ option?: boolean | DOMUtilsEventListenerOption
1063
1098
  ) {
1064
1099
  let DOMUtilsContext = this;
1065
1100
  if (element == null) {
@@ -1094,8 +1129,8 @@ export class DOMUtilsEvent {
1094
1129
  */
1095
1130
  keypress(
1096
1131
  element: DOMUtilsTargetElementType | Window | typeof globalThis,
1097
- handler: (event: DOMUtils_Event["keypress"]) => void,
1098
- option?: boolean | AddEventListenerOptions
1132
+ handler: (this: HTMLElement, event: DOMUtils_Event["keypress"]) => void,
1133
+ option?: boolean | DOMUtilsEventListenerOption
1099
1134
  ) {
1100
1135
  let DOMUtilsContext = this;
1101
1136
  if (element == null) {
@@ -1186,7 +1221,7 @@ export class DOMUtilsEvent {
1186
1221
  otherCodeList: string[],
1187
1222
  event: KeyboardEvent
1188
1223
  ) => void,
1189
- options?: AddEventListenerOptions | boolean
1224
+ options?: DOMUtilsEventListenerOption | boolean
1190
1225
  ): {
1191
1226
  removeListen(): void;
1192
1227
  } {
@@ -211,7 +211,7 @@ export declare interface DOMUtilsEventListenerOptionsAttribute {
211
211
  /**
212
212
  * 属性配置
213
213
  */
214
- option: AddEventListenerOptions;
214
+ option: DOMUtilsEventListenerOption;
215
215
  /**
216
216
  * 用户添加的事件
217
217
  */
@@ -222,6 +222,17 @@ export declare interface DOMUtilsEventListenerOptionsAttribute {
222
222
  selector?: string[];
223
223
  }
224
224
 
225
+ /**
226
+ * 事件的额外配置
227
+ */
228
+ export declare type DOMUtilsEventListenerOption = AddEventListenerOptions & {
229
+ /**
230
+ * 是否使用 event.composedPath() 来代替 event.target
231
+ *
232
+ * 一般用于设置了selector参数
233
+ */
234
+ isComposedPath?: boolean;
235
+ };
225
236
  export declare type DOMUtilsElementEventType =
226
237
  | HTMLElement
227
238
  | string