@whitesev/domutils 1.1.5 → 1.3.0

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.
@@ -0,0 +1,1259 @@
1
+ import { DOMUtilsCommonUtils } from "./DOMUtilsCommonUtils";
2
+ import { DOMUtilsData } from "./DOMUtilsData";
3
+ import { OriginPrototype } from "./DOMUtilsOriginPrototype";
4
+ import { UtilsWindowApiOption, WindowApi } from "./WindowApi";
5
+
6
+ export type DOMUtilsEventObject<T extends Node> = Event & {
7
+ target: T;
8
+ };
9
+
10
+ export declare type DOMUtilsCreateElementAttributesMap = {
11
+ style?: string;
12
+ id?: string;
13
+ class?: string;
14
+ "data-"?: string;
15
+ type?: string;
16
+ [key: string]: any;
17
+ };
18
+ /**
19
+ * 鼠标事件
20
+ * + https://blog.csdn.net/weixin_68658847/article/details/126939879
21
+ */
22
+
23
+ export interface DOMUtils_MouseEvent {
24
+ click: MouseEvent | PointerEvent;
25
+ contextmenu: MouseEvent | PointerEvent;
26
+ dblclick: MouseEvent | PointerEvent;
27
+ mousedown: MouseEvent | PointerEvent;
28
+ mouseenter: MouseEvent | PointerEvent;
29
+ mouseleave: MouseEvent | PointerEvent;
30
+ mousemove: MouseEvent | PointerEvent;
31
+ mouseover: MouseEvent | PointerEvent;
32
+ mouseout: MouseEvent | PointerEvent;
33
+ mouseup: MouseEvent | PointerEvent;
34
+ hover: MouseEvent;
35
+ }
36
+ export type DOMUtils_MouseEventType = keyof DOMUtils_MouseEvent;
37
+ /**
38
+ * 鼠标事件
39
+ */
40
+ export interface DOMUtils_KeyboardEvent {
41
+ keydown: KeyboardEvent;
42
+ keypress: KeyboardEvent;
43
+ keyup: KeyboardEvent;
44
+ }
45
+ export type DOMUtils_KeyboardEventType = keyof DOMUtils_KeyboardEvent;
46
+ /**
47
+ * 框架/对象事件
48
+ */
49
+ export interface DOMUtils_Frame_Object_Event {
50
+ abort: Event;
51
+ beforeunload: Event;
52
+ error: Event;
53
+ hashchange: Event;
54
+ load: Event;
55
+ pageshow: Event;
56
+ pagehide: Event;
57
+ resize: Event;
58
+ scroll: Event;
59
+ unload: Event;
60
+ }
61
+ export type DOMUtils_Frame_Object_EventType = keyof DOMUtils_Frame_Object_Event;
62
+ /**
63
+ * 表单事件
64
+ */
65
+ export interface DOMUtils_FormEvent {
66
+ blur: Event;
67
+ change: Event;
68
+ focus: Event;
69
+ focusin: Event;
70
+ focusout: Event;
71
+ input: Event;
72
+ reset: Event;
73
+ search: Event;
74
+ }
75
+ export type DOMUtils_FormEventType = keyof DOMUtils_FormEvent;
76
+
77
+ /**
78
+ * 剪贴板事件
79
+ */
80
+ export interface DOMUtils_ClipboardEvent {
81
+ copy: ClipboardEvent;
82
+ cut: ClipboardEvent;
83
+ paste: ClipboardEvent;
84
+ }
85
+ export type DOMUtils_ClipboardEventType = keyof DOMUtils_ClipboardEvent;
86
+
87
+ /**
88
+ * 打印事件
89
+ */
90
+ export interface DOMUtils_PrintEvent {
91
+ afterprint: Event;
92
+ beforeprint: Event;
93
+ }
94
+ export type DOMUtils_PrintEventType = keyof DOMUtils_PrintEvent;
95
+
96
+ /**
97
+ * 拖动事件
98
+ */
99
+ export interface DOMUtils_DragEvent {
100
+ drag: DragEvent;
101
+ dragend: DragEvent;
102
+ dragenter: DragEvent;
103
+ dragleave: DragEvent;
104
+ dragover: DragEvent;
105
+ dragstart: DragEvent;
106
+ drop: DragEvent;
107
+ }
108
+ export type DOMUtils_DragEventType = keyof DOMUtils_DragEvent;
109
+
110
+ /**
111
+ * 多媒体(Media)事件
112
+ */
113
+ export interface DOMUtils_MediaEvent {
114
+ abort: Event;
115
+ canplay: Event;
116
+ canplaythrough: Event;
117
+ durationchange: Event;
118
+ emptied: Event;
119
+ ended: Event;
120
+ error: Event;
121
+ loadeddata: Event;
122
+ loadedmetadata: Event;
123
+ loadstart: Event;
124
+ pause: Event;
125
+ play: Event;
126
+ playing: Event;
127
+ progress: Event;
128
+ ratechange: Event;
129
+ seeked: Event;
130
+ seeking: Event;
131
+ stalled: Event;
132
+ suspend: Event;
133
+ timeupdate: Event;
134
+ volumechange: Event;
135
+ waiting: Event;
136
+ }
137
+ export type DOMUtils_MediaEventType = keyof DOMUtils_MediaEvent;
138
+
139
+ /**
140
+ * 动画事件
141
+ */
142
+ export interface DOMUtils_AnimationEvent {
143
+ animationend: AnimationEvent;
144
+ animationiteration: AnimationEvent;
145
+ animationstart: AnimationEvent;
146
+ }
147
+ export type DOMUtils_AnimationEventType = keyof DOMUtils_AnimationEvent;
148
+
149
+ /**
150
+ * 过渡事件
151
+ */
152
+ export interface DOMUtils_TransitionEvent {
153
+ transitionend: TransitionEvent;
154
+ }
155
+ export type DOMUtils_TransitionEventType = keyof DOMUtils_TransitionEvent;
156
+
157
+ /**
158
+ * 触摸事件
159
+ */
160
+ export interface DOMUtils_TouchEvent {
161
+ touchstart: TouchEvent;
162
+ touchmove: TouchEvent;
163
+ touchend: TouchEvent;
164
+ touchcancel: TouchEvent;
165
+ touchenter: TouchEvent;
166
+ touchleave: TouchEvent;
167
+ }
168
+ export type DOMUtils_TouchEventType = keyof DOMUtils_TouchEvent;
169
+ /**
170
+ * 其它事件
171
+ */
172
+ export interface DOMUtils_OtherEvent {
173
+ message: Event;
174
+ online: Event;
175
+ offline: Event;
176
+ popstate: Event;
177
+ show: Event;
178
+ storage: Event;
179
+ toggle: Event;
180
+ wheel: Event;
181
+ propertychange: Event;
182
+ fullscreenchange: Event;
183
+ DOMContentLoaded: Event;
184
+ }
185
+ export type DOMUtils_OtherEventType = keyof DOMUtils_OtherEvent;
186
+
187
+ /**
188
+ * 全部事件
189
+ */
190
+ export declare type DOMUtils_Event = DOMUtils_MouseEvent &
191
+ DOMUtils_KeyboardEvent &
192
+ DOMUtils_Frame_Object_Event &
193
+ DOMUtils_FormEvent &
194
+ DOMUtils_ClipboardEvent &
195
+ DOMUtils_PrintEvent &
196
+ DOMUtils_DragEvent &
197
+ DOMUtils_MediaEvent &
198
+ DOMUtils_AnimationEvent &
199
+ DOMUtils_TransitionEvent &
200
+ DOMUtils_TouchEvent &
201
+ DOMUtils_OtherEvent;
202
+
203
+ /**
204
+ * 事件类型
205
+ */
206
+ export declare type DOMUtils_EventType = keyof DOMUtils_Event;
207
+
208
+ /**
209
+ * 元素上的events属性
210
+ */
211
+ export declare interface DOMUtilsEventListenerOptionsAttribute {
212
+ /**
213
+ * 自定义的ownCallBack
214
+ */
215
+ callback: () => void;
216
+ /**
217
+ * 属性配置
218
+ */
219
+ option: AddEventListenerOptions;
220
+ /**
221
+ * 用户添加的事件
222
+ */
223
+ originCallBack: () => void;
224
+ /**
225
+ * 子元素选择器
226
+ */
227
+ selector?: string;
228
+ }
229
+
230
+ export declare type DOMUtilsElementEventType =
231
+ | HTMLElement
232
+ | string
233
+ | NodeList
234
+ | (HTMLElement | Window | Document | Element | typeof globalThis)[]
235
+ | Window
236
+ | Document
237
+ | Element
238
+ | null
239
+ | typeof globalThis
240
+ | ShadowRoot
241
+ | EventTarget
242
+ | ChildNode
243
+ | Node;
244
+
245
+ export class DOMUtilsEvent {
246
+ windowApi: UtilsWindowApiOption;
247
+ constructor(windowApiOption?: UtilsWindowApiOption) {
248
+ this.windowApi = new WindowApi(windowApiOption);
249
+ }
250
+ /**
251
+ * 绑定事件
252
+ * @param element 需要绑定的元素|元素数组|window
253
+ * @param eventType 需要监听的事件
254
+ * @param callback 绑定事件触发的回调函数
255
+ * @param option
256
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
257
+ * + once 表示事件是否只触发一次。默认为false
258
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
259
+ * @example
260
+ * // 监听元素a.xx的click事件
261
+ * DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
262
+ * console.log("事件触发",event)
263
+ * })
264
+ * DOMUtils.on("a.xx","click",(event)=>{
265
+ * console.log("事件触发",event)
266
+ * })
267
+ */
268
+ on<T extends DOMUtils_EventType>(
269
+ element: DOMUtilsElementEventType,
270
+ eventType: T | T[],
271
+ callback: (event: DOMUtils_Event[T]) => void,
272
+ option?: boolean | AddEventListenerOptions
273
+ ): void;
274
+ /**
275
+ * 绑定事件
276
+ * @param element 需要绑定的元素|元素数组|window
277
+ * @param eventType 需要监听的事件
278
+ * @param callback 绑定事件触发的回调函数
279
+ * @param option
280
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
281
+ * + once 表示事件是否只触发一次。默认为false
282
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
283
+ * @example
284
+ * // 监听元素a.xx的click事件
285
+ * DOMUtils.on(document.querySelector("a.xx"),"click",(event)=>{
286
+ * console.log("事件触发",event)
287
+ * })
288
+ * DOMUtils.on("a.xx","click",(event)=>{
289
+ * console.log("事件触发",event)
290
+ * })
291
+ */
292
+ on<T extends Event>(
293
+ element: DOMUtilsElementEventType,
294
+ eventType: string,
295
+ callback: (event: T) => void,
296
+ option?: boolean | AddEventListenerOptions
297
+ ): void;
298
+ /**
299
+ * 绑定事件
300
+ * @param element 需要绑定的元素|元素数组|window
301
+ * @param eventType 需要监听的事件
302
+ * @param selector 子元素选择器
303
+ * @param callback 绑定事件触发的回调函数
304
+ * @param option
305
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
306
+ * + once 表示事件是否只触发一次。默认为false
307
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
308
+ * @example
309
+ * // 监听元素a.xx的click、tap、hover事件
310
+ * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event)=>{
311
+ * console.log("事件触发",event)
312
+ * })
313
+ * DOMUtils.on("a.xx",["click","tap","hover"],(event)=>{
314
+ * console.log("事件触发",event)
315
+ * })
316
+ * @example
317
+ * // 监听全局document下的子元素a.xx的click事件
318
+ * DOMUtils.on(document,"click tap hover","a.xx",(event)=>{
319
+ * console.log("事件触发",event)
320
+ * })
321
+ */
322
+ on<T extends DOMUtils_EventType>(
323
+ element: DOMUtilsElementEventType,
324
+ eventType: T | T[],
325
+ selector: string | undefined | null,
326
+ callback: (event: DOMUtils_Event[T]) => void,
327
+ option?: boolean | AddEventListenerOptions
328
+ ): void;
329
+ /**
330
+ * 绑定事件
331
+ * @param element 需要绑定的元素|元素数组|window
332
+ * @param eventType 需要监听的事件
333
+ * @param selector 子元素选择器
334
+ * @param callback 绑定事件触发的回调函数
335
+ * @param option
336
+ * + capture 表示事件是否在捕获阶段触发。默认为false,即在冒泡阶段触发
337
+ * + once 表示事件是否只触发一次。默认为false
338
+ * + passive 表示事件监听器是否不会调用preventDefault()。默认为false
339
+ * @example
340
+ * // 监听元素a.xx的click、tap、hover事件
341
+ * DOMUtils.on(document.querySelector("a.xx"),"click tap hover",(event)=>{
342
+ * console.log("事件触发",event)
343
+ * })
344
+ * DOMUtils.on("a.xx",["click","tap","hover"],(event)=>{
345
+ * console.log("事件触发",event)
346
+ * })
347
+ * @example
348
+ * // 监听全局document下的子元素a.xx的click事件
349
+ * DOMUtils.on(document,"click tap hover","a.xx",(event)=>{
350
+ * console.log("事件触发",event)
351
+ * })
352
+ */
353
+ on<T extends Event>(
354
+ element: DOMUtilsElementEventType,
355
+ eventType: string,
356
+ selector: string | undefined | null,
357
+ callback: (event: T) => void,
358
+ option?: boolean | AddEventListenerOptions
359
+ ): void;
360
+ on<T extends Event>(
361
+ element:
362
+ | HTMLElement
363
+ | string
364
+ | NodeList
365
+ | HTMLElement[]
366
+ | Window
367
+ | Document
368
+ | Element
369
+ | null
370
+ | typeof globalThis,
371
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
372
+ selector: string | undefined | ((event: T) => void) | null,
373
+ callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
374
+ option?: boolean | AddEventListenerOptions
375
+ ) {
376
+ /**
377
+ * 获取option配置
378
+ * @param args
379
+ * @param startIndex
380
+ * @param option
381
+ */
382
+ function getOption(
383
+ args: IArguments,
384
+ startIndex: number,
385
+ option: AddEventListenerOptions
386
+ ) {
387
+ if (typeof args[startIndex] === "boolean") {
388
+ option.capture = args[startIndex];
389
+ if (typeof args[startIndex + 1] === "boolean") {
390
+ option.once = args[startIndex + 1];
391
+ }
392
+ if (typeof args[startIndex + 2] === "boolean") {
393
+ option.passive = args[startIndex + 2];
394
+ }
395
+ } else if (
396
+ typeof args[startIndex] === "object" &&
397
+ ("capture" in args[startIndex] ||
398
+ "once" in args[startIndex] ||
399
+ "passive" in args[startIndex])
400
+ ) {
401
+ option.capture = args[startIndex].capture;
402
+ option.once = args[startIndex].once;
403
+ option.passive = args[startIndex].passive;
404
+ }
405
+ return option;
406
+ }
407
+
408
+ let DOMUtilsContext = this;
409
+ let args = arguments;
410
+ if (typeof element === "string") {
411
+ element = DOMUtilsContext.windowApi.document.querySelectorAll(element);
412
+ }
413
+ if (element == null) {
414
+ return;
415
+ }
416
+ let elementList: HTMLElement[] = [];
417
+ if (element instanceof NodeList || Array.isArray(element)) {
418
+ element = element as HTMLElement[];
419
+ elementList = [...element];
420
+ } else {
421
+ elementList.push(element as HTMLElement);
422
+ }
423
+
424
+ let eventTypeList: string[] = [];
425
+ if (Array.isArray(eventType)) {
426
+ eventTypeList = eventTypeList.concat(eventType as string[]);
427
+ } else if (typeof eventType === "string") {
428
+ eventTypeList = eventTypeList.concat(eventType.split(" "));
429
+ }
430
+ let _selector_: string | undefined = selector as any;
431
+ let _callback_: (event: T) => void = callback as any;
432
+ let _option_: AddEventListenerOptions = {
433
+ capture: false,
434
+ once: false,
435
+ passive: false,
436
+ };
437
+ if (typeof selector === "function") {
438
+ /* 这是为没有selector的情况 */
439
+ _selector_ = void 0;
440
+ _callback_ = selector;
441
+ _option_ = getOption(args, 3, _option_);
442
+ } else {
443
+ /* 这是存在selector的情况 */
444
+ _option_ = getOption(args, 4, _option_);
445
+ }
446
+ /**
447
+ * 如果是once,那么删除该监听和元素上的事件和监听
448
+ */
449
+ function checkOptionOnceToRemoveEventListener() {
450
+ if (_option_.once) {
451
+ DOMUtilsContext.off(
452
+ element,
453
+ eventType as any,
454
+ selector as any,
455
+ callback as any,
456
+ option
457
+ );
458
+ }
459
+ }
460
+ elementList.forEach((elementItem) => {
461
+ function ownCallBack(event: Event) {
462
+ let target = event.target as HTMLElement;
463
+ if (_selector_) {
464
+ /* 存在自定义子元素选择器 */
465
+ let totalParent = DOMUtilsCommonUtils.isWin(elementItem)
466
+ ? DOMUtilsContext.windowApi.document.documentElement
467
+ : elementItem;
468
+ if (target.matches(_selector_)) {
469
+ /* 当前目标可以被selector所匹配到 */
470
+ _callback_.call(target, event as any);
471
+ checkOptionOnceToRemoveEventListener();
472
+ } else if (
473
+ target.closest(_selector_) &&
474
+ totalParent.contains(target.closest(_selector_))
475
+ ) {
476
+ /* 在上层与主元素之间寻找可以被selector所匹配到的 */
477
+ let closestElement = target.closest(_selector_);
478
+ /* event的target值不能直接修改 */
479
+ OriginPrototype.Object.defineProperty(event, "target", {
480
+ get() {
481
+ return closestElement;
482
+ },
483
+ });
484
+ _callback_.call(closestElement, event as any);
485
+ checkOptionOnceToRemoveEventListener();
486
+ }
487
+ } else {
488
+ _callback_.call(elementItem, event as any);
489
+ checkOptionOnceToRemoveEventListener();
490
+ }
491
+ }
492
+
493
+ /* 遍历事件名设置元素事件 */
494
+ eventTypeList.forEach((eventName) => {
495
+ elementItem.addEventListener(eventName, ownCallBack, _option_);
496
+
497
+ if (_callback_ && (_callback_ as any).delegate) {
498
+ elementItem.setAttribute("data-delegate", _selector_ as string);
499
+ }
500
+ /* 获取对象上的事件 */
501
+ let elementEvents =
502
+ (elementItem as any)[DOMUtilsData.SymbolEvents] || {};
503
+ /* 初始化对象上的xx事件 */
504
+ elementEvents[eventName] = elementEvents[eventName] || [];
505
+ elementEvents[eventName].push({
506
+ selector: _selector_,
507
+ option: _option_,
508
+ callback: ownCallBack,
509
+ originCallBack: _callback_,
510
+ });
511
+ /* 覆盖事件 */
512
+ (elementItem as any)[DOMUtilsData.SymbolEvents] = elementEvents;
513
+ });
514
+ });
515
+ }
516
+ /**
517
+ * 取消绑定事件
518
+ * @param element 需要取消绑定的元素|元素数组
519
+ * @param eventType 需要取消监听的事件
520
+ * @param callback 通过DOMUtils.on绑定的事件函数
521
+ * @param option
522
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
523
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
524
+ * @example
525
+ * // 取消监听元素a.xx的click事件
526
+ * DOMUtils.off(document.querySelector("a.xx"),"click")
527
+ * DOMUtils.off("a.xx","click")
528
+ */
529
+ off<T extends DOMUtils_EventType>(
530
+ element: DOMUtilsElementEventType,
531
+ eventType: T | T[],
532
+ callback?: (event: DOMUtils_Event[T]) => void,
533
+ option?: boolean | AddEventListenerOptions,
534
+ filter?: (
535
+ value: DOMUtilsEventListenerOptionsAttribute,
536
+ index: number,
537
+ array: DOMUtilsEventListenerOptionsAttribute[]
538
+ ) => boolean
539
+ ): void;
540
+ /**
541
+ * 取消绑定事件
542
+ * @param element 需要取消绑定的元素|元素数组
543
+ * @param eventType 需要取消监听的事件
544
+ * @param callback 通过DOMUtils.on绑定的事件函数
545
+ * @param option
546
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
547
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
548
+ * @example
549
+ * // 取消监听元素a.xx的click事件
550
+ * DOMUtils.off(document.querySelector("a.xx"),"click")
551
+ * DOMUtils.off("a.xx","click")
552
+ */
553
+ off<T extends Event>(
554
+ element: DOMUtilsElementEventType,
555
+ eventType: string,
556
+ callback?: (event: T) => void,
557
+ option?: boolean | AddEventListenerOptions,
558
+ filter?: (
559
+ value: DOMUtilsEventListenerOptionsAttribute,
560
+ index: number,
561
+ array: DOMUtilsEventListenerOptionsAttribute[]
562
+ ) => boolean
563
+ ): void;
564
+ /**
565
+ * 取消绑定事件
566
+ * @param element 需要取消绑定的元素|元素数组
567
+ * @param eventType 需要取消监听的事件
568
+ * @param selector 子元素选择器
569
+ * @param callback 通过DOMUtils.on绑定的事件函数
570
+ * @param option
571
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
572
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
573
+ * @example
574
+ * // 取消监听元素a.xx的click、tap、hover事件
575
+ * DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
576
+ * DOMUtils.off("a.xx",["click","tap","hover"])
577
+ */
578
+ off<T extends DOMUtils_EventType>(
579
+ element: DOMUtilsElementEventType,
580
+ eventType: T | T[],
581
+ selector?: string | undefined,
582
+ callback?: (event: DOMUtils_Event[T]) => void,
583
+ option?: boolean | AddEventListenerOptions,
584
+ filter?: (
585
+ value: DOMUtilsEventListenerOptionsAttribute,
586
+ index: number,
587
+ array: DOMUtilsEventListenerOptionsAttribute[]
588
+ ) => boolean
589
+ ): void;
590
+ /**
591
+ * 取消绑定事件
592
+ * @param element 需要取消绑定的元素|元素数组
593
+ * @param eventType 需要取消监听的事件
594
+ * @param selector 子元素选择器
595
+ * @param callback 通过DOMUtils.on绑定的事件函数
596
+ * @param option
597
+ * + capture 如果在添加事件监听器时指定了useCapture为true,则在移除事件监听器时也必须指定为true
598
+ * @param filter (可选)过滤函数,对元素属性上的事件进行过滤出想要删除的事件
599
+ * @example
600
+ * // 取消监听元素a.xx的click、tap、hover事件
601
+ * DOMUtils.off(document.querySelector("a.xx"),"click tap hover")
602
+ * DOMUtils.off("a.xx",["click","tap","hover"])
603
+ */
604
+ off<T extends Event>(
605
+ element: DOMUtilsElementEventType,
606
+ eventType: string,
607
+ selector?: string | undefined,
608
+ callback?: (event: T) => void,
609
+ option?: boolean | AddEventListenerOptions,
610
+ filter?: (
611
+ value: DOMUtilsEventListenerOptionsAttribute,
612
+ index: number,
613
+ array: DOMUtilsEventListenerOptionsAttribute[]
614
+ ) => boolean
615
+ ): void;
616
+ off<T extends Event>(
617
+ element:
618
+ | HTMLElement
619
+ | string
620
+ | NodeList
621
+ | HTMLElement[]
622
+ | Window
623
+ | Document
624
+ | Element
625
+ | null
626
+ | typeof globalThis,
627
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
628
+ selector?: string | undefined | ((event: T) => void),
629
+ callback?: ((event: T) => void) | boolean | AddEventListenerOptions,
630
+ option?:
631
+ | boolean
632
+ | AddEventListenerOptions
633
+ | ((
634
+ value: DOMUtilsEventListenerOptionsAttribute,
635
+ index: number,
636
+ array: DOMUtilsEventListenerOptionsAttribute[]
637
+ ) => boolean),
638
+ filter?: (
639
+ value: DOMUtilsEventListenerOptionsAttribute,
640
+ index: number,
641
+ array: DOMUtilsEventListenerOptionsAttribute[]
642
+ ) => boolean
643
+ ) {
644
+ /**
645
+ * 获取option配置
646
+ * @param args1
647
+ * @param startIndex
648
+ * @param option
649
+ */
650
+ function getOption(
651
+ args1: IArguments,
652
+ startIndex: number,
653
+ option: EventListenerOptions
654
+ ) {
655
+ if (typeof args1[startIndex] === "boolean") {
656
+ option.capture = args1[startIndex];
657
+ } else if (
658
+ typeof args1[startIndex] === "object" &&
659
+ "capture" in args1[startIndex]
660
+ ) {
661
+ option.capture = args1[startIndex].capture;
662
+ }
663
+ return option;
664
+ }
665
+ let DOMUtilsContext = this;
666
+ let args = arguments;
667
+ if (typeof element === "string") {
668
+ element = DOMUtilsContext.windowApi.document.querySelectorAll(element);
669
+ }
670
+ if (element == null) {
671
+ return;
672
+ }
673
+ let elementList: HTMLElement[] = [];
674
+ if (element instanceof NodeList || Array.isArray(element)) {
675
+ element = element as HTMLElement[];
676
+ elementList = [...element];
677
+ } else {
678
+ elementList.push(element as HTMLElement);
679
+ }
680
+ let eventTypeList: string[] = [];
681
+ if (Array.isArray(eventType)) {
682
+ eventTypeList = eventTypeList.concat(eventType as string[]);
683
+ } else if (typeof eventType === "string") {
684
+ eventTypeList = eventTypeList.concat(eventType.split(" "));
685
+ }
686
+ /**
687
+ * 子元素选择器
688
+ */
689
+ let _selector_: string | undefined = selector as any;
690
+ /**
691
+ * 事件的回调函数
692
+ */
693
+ let _callback_: (event: T) => void = callback as any;
694
+
695
+ /**
696
+ * 事件的配置
697
+ */
698
+ let _option_: EventListenerOptions = {
699
+ capture: false,
700
+ };
701
+ if (typeof selector === "function") {
702
+ /* 这是为没有selector的情况 */
703
+ _selector_ = void 0;
704
+ _callback_ = selector;
705
+ _option_ = getOption(args, 3, _option_);
706
+ } else {
707
+ _option_ = getOption(args, 4, _option_);
708
+ }
709
+ elementList.forEach((elementItem) => {
710
+ /* 获取对象上的事件 */
711
+ let elementEvents = (elementItem as any)[DOMUtilsData.SymbolEvents] || {};
712
+ eventTypeList.forEach((eventName) => {
713
+ let handlers: DOMUtilsEventListenerOptionsAttribute[] =
714
+ elementEvents[eventName] || [];
715
+ if (typeof filter === "function") {
716
+ handlers = handlers.filter(filter);
717
+ }
718
+ for (let index = 0; index < handlers.length; index++) {
719
+ let handler = handlers[index];
720
+ let flag = false;
721
+ if (!_selector_ || handler.selector === _selector_) {
722
+ /* selector不为空,进行selector判断 */
723
+ flag = true;
724
+ }
725
+ if (
726
+ !_callback_ ||
727
+ handler.callback === _callback_ ||
728
+ handler.originCallBack === _callback_
729
+ ) {
730
+ /* callback不为空,进行callback判断 */
731
+ flag = true;
732
+ }
733
+
734
+ if (flag) {
735
+ elementItem.removeEventListener(
736
+ eventName,
737
+ handler.callback,
738
+ _option_
739
+ );
740
+ handlers.splice(index--, 1);
741
+ }
742
+ }
743
+ if (handlers.length === 0) {
744
+ /* 如果没有任意的handler,那么删除该属性 */
745
+ DOMUtilsCommonUtils.delete(elementEvents, eventType);
746
+ }
747
+ });
748
+ (elementItem as any)[DOMUtilsData.SymbolEvents] = elementEvents;
749
+ });
750
+ }
751
+ /**
752
+ * 取消绑定所有的事件
753
+ * @param element 需要取消绑定的元素|元素数组
754
+ * @param eventType (可选)需要取消监听的事件
755
+ */
756
+ offAll(element: DOMUtilsElementEventType, eventType?: string): void;
757
+ /**
758
+ * 取消绑定所有的事件
759
+ * @param element 需要取消绑定的元素|元素数组
760
+ * @param eventType (可选)需要取消监听的事件
761
+ */
762
+ offAll(
763
+ element: DOMUtilsElementEventType,
764
+ eventType?: DOMUtils_EventType | DOMUtils_EventType[]
765
+ ): void;
766
+ /**
767
+ * 取消绑定所有的事件
768
+ * @param element 需要取消绑定的元素|元素数组
769
+ * @param eventType (可选)需要取消监听的事件
770
+ */
771
+ offAll(
772
+ element: DOMUtilsElementEventType,
773
+ eventType?: DOMUtils_EventType | DOMUtils_EventType[] | string
774
+ ) {
775
+ let DOMUtilsContext = this;
776
+ if (typeof element === "string") {
777
+ element = DOMUtilsContext.windowApi.document.querySelectorAll(element);
778
+ }
779
+ if (element == null) {
780
+ return;
781
+ }
782
+ let elementList: HTMLElement[] = [];
783
+ if (element instanceof NodeList || Array.isArray(element)) {
784
+ elementList = [...(element as HTMLElement[])];
785
+ } else {
786
+ elementList.push(element as HTMLElement);
787
+ }
788
+
789
+ let eventTypeList: string[] = [];
790
+ if (Array.isArray(eventType)) {
791
+ eventTypeList = eventTypeList.concat(eventType as string[]);
792
+ } else if (typeof eventType === "string") {
793
+ eventTypeList = eventTypeList.concat(eventType.split(" "));
794
+ }
795
+ elementList.forEach((elementItem) => {
796
+ Object.getOwnPropertySymbols(elementItem).forEach((symbolEvents) => {
797
+ if (!symbolEvents.toString().startsWith("Symbol(events_")) {
798
+ return;
799
+ }
800
+ let elementEvents = (elementItem as any)[symbolEvents] || {};
801
+ let iterEventNameList = eventTypeList.length
802
+ ? eventTypeList
803
+ : Object.keys(elementEvents);
804
+ iterEventNameList.forEach((eventName) => {
805
+ let handlers = elementEvents[eventName];
806
+ if (!handlers) {
807
+ return;
808
+ }
809
+ for (const handler of handlers) {
810
+ elementItem.removeEventListener(eventName, handler.callback, {
811
+ capture: handler["option"]["capture"],
812
+ });
813
+ }
814
+ DOMUtilsCommonUtils.delete(
815
+ (elementItem as any)[symbolEvents],
816
+ eventName
817
+ );
818
+ });
819
+ });
820
+ });
821
+ }
822
+
823
+ /**
824
+ * 等待文档加载完成后执行指定的函数
825
+ * @param callback 需要执行的函数
826
+ * @example
827
+ * DOMUtils.ready(function(){
828
+ * console.log("文档加载完毕")
829
+ * })
830
+ */
831
+ ready<T extends Function>(callback: T) {
832
+ if (typeof callback !== "function") {
833
+ return;
834
+ }
835
+ let DOMUtilsContext = this;
836
+ /**
837
+ * 检测文档是否加载完毕
838
+ */
839
+ function checkDOMReadyState() {
840
+ try {
841
+ if (
842
+ DOMUtilsContext.windowApi.document.readyState === "complete" ||
843
+ (DOMUtilsContext.windowApi.document.readyState !== "loading" &&
844
+ !(DOMUtilsContext.windowApi.document.documentElement as any)
845
+ .doScroll)
846
+ ) {
847
+ return true;
848
+ } else {
849
+ return false;
850
+ }
851
+ } catch (error) {
852
+ return false;
853
+ }
854
+ }
855
+ /**
856
+ * 成功加载完毕后触发的回调函数
857
+ */
858
+ function completed() {
859
+ removeDomReadyListener();
860
+ callback();
861
+ }
862
+
863
+ let targetList = [
864
+ {
865
+ target: DOMUtilsContext.windowApi.document,
866
+ eventType: "DOMContentLoaded",
867
+ callback: completed,
868
+ },
869
+ {
870
+ target: DOMUtilsContext.windowApi.window,
871
+ eventType: "load",
872
+ callback: completed,
873
+ },
874
+ ];
875
+ /**
876
+ * 添加监听
877
+ */
878
+ function addDomReadyListener() {
879
+ for (let index = 0; index < targetList.length; index++) {
880
+ let item = targetList[index];
881
+ item.target.addEventListener(item.eventType, item.callback);
882
+ }
883
+ }
884
+ /**
885
+ * 移除监听
886
+ */
887
+ function removeDomReadyListener() {
888
+ for (let index = 0; index < targetList.length; index++) {
889
+ let item = targetList[index];
890
+ item.target.removeEventListener(item.eventType, item.callback);
891
+ }
892
+ }
893
+ if (checkDOMReadyState()) {
894
+ /* 检查document状态 */
895
+ setTimeout(callback);
896
+ } else {
897
+ /* 添加监听 */
898
+ addDomReadyListener();
899
+ }
900
+ }
901
+ /**
902
+ * 主动触发事件
903
+ * @param element 需要触发的元素|元素数组|window
904
+ * @param eventType 需要触发的事件
905
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
906
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
907
+ * @example
908
+ * // 触发元素a.xx的click事件
909
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
910
+ * DOMUtils.trigger("a.xx","click")
911
+ * // 触发元素a.xx的click、tap、hover事件
912
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
913
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
914
+ */
915
+ trigger(
916
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
917
+ eventType: string,
918
+ details?: object,
919
+ useDispatchToTriggerEvent?: boolean
920
+ ): void;
921
+ /**
922
+ * 主动触发事件
923
+ * @param element 需要触发的元素|元素数组|window
924
+ * @param eventType 需要触发的事件
925
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
926
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
927
+ * @example
928
+ * // 触发元素a.xx的click事件
929
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
930
+ * DOMUtils.trigger("a.xx","click")
931
+ * // 触发元素a.xx的click、tap、hover事件
932
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
933
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
934
+ */
935
+ trigger(
936
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
937
+ eventType: DOMUtils_EventType | DOMUtils_EventType[],
938
+ details?: object,
939
+ useDispatchToTriggerEvent?: boolean
940
+ ): void;
941
+ /**
942
+ * 主动触发事件
943
+ * @param element 需要触发的元素|元素数组|window
944
+ * @param eventType 需要触发的事件
945
+ * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
946
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true
947
+ * @example
948
+ * // 触发元素a.xx的click事件
949
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click")
950
+ * DOMUtils.trigger("a.xx","click")
951
+ * // 触发元素a.xx的click、tap、hover事件
952
+ * DOMUtils.trigger(document.querySelector("a.xx"),"click tap hover")
953
+ * DOMUtils.trigger("a.xx",["click","tap","hover"])
954
+ */
955
+ trigger(
956
+ element: HTMLElement | string | NodeList | any[] | Window | Document,
957
+ eventType: DOMUtils_EventType | DOMUtils_EventType[] | string,
958
+ details?: object,
959
+ useDispatchToTriggerEvent: boolean = true
960
+ ) {
961
+ let DOMUtilsContext = this;
962
+ if (typeof element === "string") {
963
+ element = DOMUtilsContext.windowApi.document.querySelector(
964
+ element
965
+ ) as HTMLElement;
966
+ }
967
+ if (element == null) {
968
+ return;
969
+ }
970
+ let elementList = [];
971
+ if (element instanceof NodeList || Array.isArray(element)) {
972
+ element = element as HTMLElement[];
973
+ elementList = [...element];
974
+ } else {
975
+ elementList = [element];
976
+ }
977
+ let eventTypeList: string[] = [];
978
+ if (Array.isArray(eventType)) {
979
+ eventTypeList = eventType as string[];
980
+ } else if (typeof eventType === "string") {
981
+ eventTypeList = eventType.split(" ");
982
+ }
983
+
984
+ elementList.forEach((elementItem) => {
985
+ /* 获取对象上的事件 */
986
+ let events = elementItem[DOMUtilsData.SymbolEvents] || {};
987
+ eventTypeList.forEach((_eventType_) => {
988
+ let event: Event = null as any;
989
+ if (details && details instanceof Event) {
990
+ event = details;
991
+ } else {
992
+ event = new Event(_eventType_);
993
+ if (details) {
994
+ Object.keys(details).forEach((keyName) => {
995
+ (event as any)[keyName] = (details as any)[keyName];
996
+ });
997
+ }
998
+ }
999
+ if (useDispatchToTriggerEvent == false && _eventType_ in events) {
1000
+ events[_eventType_].forEach((eventsItem: any) => {
1001
+ eventsItem.callback(event);
1002
+ });
1003
+ } else {
1004
+ elementItem.dispatchEvent(event);
1005
+ }
1006
+ });
1007
+ });
1008
+ }
1009
+
1010
+ /**
1011
+ * 绑定或触发元素的click事件
1012
+ * @param element 目标元素
1013
+ * @param handler (可选)事件处理函数
1014
+ * @param details (可选)赋予触发的Event的额外属性
1015
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
1016
+ * @example
1017
+ * // 触发元素a.xx的click事件
1018
+ * DOMUtils.click(document.querySelector("a.xx"))
1019
+ * DOMUtils.click("a.xx")
1020
+ * DOMUtils.click("a.xx",function(){
1021
+ * console.log("触发click事件成功")
1022
+ * })
1023
+ * */
1024
+ click(
1025
+ element: HTMLElement | string | Window,
1026
+ handler?: (event: DOMUtils_Event["click"]) => void,
1027
+ details?: any,
1028
+ useDispatchToTriggerEvent?: boolean
1029
+ ) {
1030
+ let DOMUtilsContext = this;
1031
+ if (typeof element === "string") {
1032
+ element = DOMUtilsContext.windowApi.document.querySelector(
1033
+ element
1034
+ ) as HTMLElement;
1035
+ }
1036
+ if (element == null) {
1037
+ return;
1038
+ }
1039
+ if (handler == null) {
1040
+ DOMUtilsContext.trigger(
1041
+ element,
1042
+ "click",
1043
+ details,
1044
+ useDispatchToTriggerEvent
1045
+ );
1046
+ } else {
1047
+ DOMUtilsContext.on(element, "click", null, handler);
1048
+ }
1049
+ }
1050
+ /**
1051
+ * 绑定或触发元素的blur事件
1052
+ * @param element 目标元素
1053
+ * @param handler (可选)事件处理函数
1054
+ * @param details (可选)赋予触发的Event的额外属性
1055
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
1056
+ * @example
1057
+ * // 触发元素a.xx的blur事件
1058
+ * DOMUtils.blur(document.querySelector("a.xx"))
1059
+ * DOMUtils.blur("a.xx")
1060
+ * DOMUtils.blur("a.xx",function(){
1061
+ * console.log("触发blur事件成功")
1062
+ * })
1063
+ * */
1064
+ blur(
1065
+ element: HTMLElement | string | Window,
1066
+ handler?: (event: DOMUtils_Event["blur"]) => void,
1067
+ details?: object,
1068
+ useDispatchToTriggerEvent?: boolean
1069
+ ) {
1070
+ let DOMUtilsContext = this;
1071
+ if (typeof element === "string") {
1072
+ element = DOMUtilsContext.windowApi.document.querySelector(
1073
+ element
1074
+ ) as HTMLElement;
1075
+ }
1076
+ if (element == null) {
1077
+ return;
1078
+ }
1079
+ if (handler === null) {
1080
+ DOMUtilsContext.trigger(
1081
+ element,
1082
+ "blur",
1083
+ details,
1084
+ useDispatchToTriggerEvent
1085
+ );
1086
+ } else {
1087
+ DOMUtilsContext.on(
1088
+ element,
1089
+ "blur",
1090
+ null,
1091
+ handler as (event: Event) => void
1092
+ );
1093
+ }
1094
+ }
1095
+ /**
1096
+ * 绑定或触发元素的focus事件
1097
+ * @param element 目标元素
1098
+ * @param handler (可选)事件处理函数
1099
+ * @param details (可选)赋予触发的Event的额外属性
1100
+ * @param useDispatchToTriggerEvent (可选)是否使用dispatchEvent来触发事件,默认true
1101
+ * @example
1102
+ * // 触发元素a.xx的focus事件
1103
+ * DOMUtils.focus(document.querySelector("a.xx"))
1104
+ * DOMUtils.focus("a.xx")
1105
+ * DOMUtils.focus("a.xx",function(){
1106
+ * console.log("触发focus事件成功")
1107
+ * })
1108
+ * */
1109
+ focus(
1110
+ element: HTMLElement | string | Window,
1111
+ handler?: (event: DOMUtils_Event["focus"]) => void,
1112
+ details?: object,
1113
+ useDispatchToTriggerEvent?: boolean
1114
+ ) {
1115
+ let DOMUtilsContext = this;
1116
+ if (typeof element === "string") {
1117
+ element = DOMUtilsContext.windowApi.document.querySelector(
1118
+ element
1119
+ ) as HTMLElement;
1120
+ }
1121
+ if (element == null) {
1122
+ return;
1123
+ }
1124
+ if (handler == null) {
1125
+ DOMUtilsContext.trigger(
1126
+ element,
1127
+ "focus",
1128
+ details,
1129
+ useDispatchToTriggerEvent
1130
+ );
1131
+ } else {
1132
+ DOMUtilsContext.on(element, "focus", null, handler);
1133
+ }
1134
+ }
1135
+ /**
1136
+ * 当鼠标移入或移出元素时触发事件
1137
+ * @param element 当前元素
1138
+ * @param handler 事件处理函数
1139
+ * @param option 配置
1140
+ * @example
1141
+ * // 监听a.xx元素的移入或移出
1142
+ * DOMUtils.hover(document.querySelector("a.xx"),()=>{
1143
+ * console.log("移入/移除");
1144
+ * })
1145
+ * DOMUtils.hover("a.xx",()=>{
1146
+ * console.log("移入/移除");
1147
+ * })
1148
+ */
1149
+ hover(
1150
+ element: HTMLElement | string,
1151
+ handler: (event: DOMUtils_Event["hover"]) => void,
1152
+ option?: boolean | AddEventListenerOptions
1153
+ ) {
1154
+ let DOMUtilsContext = this;
1155
+ if (typeof element === "string") {
1156
+ element = DOMUtilsContext.windowApi.document.querySelector(
1157
+ element
1158
+ ) as HTMLElement;
1159
+ }
1160
+ if (element == null) {
1161
+ return;
1162
+ }
1163
+ DOMUtilsContext.on(element, "mouseenter", null, handler, option);
1164
+ DOMUtilsContext.on(element, "mouseleave", null, handler, option);
1165
+ }
1166
+ /**
1167
+ * 当按键松开时触发事件
1168
+ * keydown - > keypress - > keyup
1169
+ * @param target 当前元素
1170
+ * @param handler 事件处理函数
1171
+ * @param option 配置
1172
+ * @example
1173
+ * // 监听a.xx元素的按键松开
1174
+ * DOMUtils.keyup(document.querySelector("a.xx"),()=>{
1175
+ * console.log("按键松开");
1176
+ * })
1177
+ * DOMUtils.keyup("a.xx",()=>{
1178
+ * console.log("按键松开");
1179
+ * })
1180
+ */
1181
+ keyup(
1182
+ target: HTMLElement | string | Window | typeof globalThis,
1183
+ handler: (event: DOMUtils_Event["keyup"]) => void,
1184
+ option?: boolean | AddEventListenerOptions
1185
+ ) {
1186
+ let DOMUtilsContext = this;
1187
+ if (target == null) {
1188
+ return;
1189
+ }
1190
+ if (typeof target === "string") {
1191
+ target = DOMUtilsContext.windowApi.document.querySelector(
1192
+ target
1193
+ ) as HTMLElement;
1194
+ }
1195
+ DOMUtilsContext.on(target, "keyup", null, handler, option);
1196
+ }
1197
+ /**
1198
+ * 当按键按下时触发事件
1199
+ * keydown - > keypress - > keyup
1200
+ * @param target 目标
1201
+ * @param handler 事件处理函数
1202
+ * @param option 配置
1203
+ * @example
1204
+ * // 监听a.xx元素的按键按下
1205
+ * DOMUtils.keydown(document.querySelector("a.xx"),()=>{
1206
+ * console.log("按键按下");
1207
+ * })
1208
+ * DOMUtils.keydown("a.xx",()=>{
1209
+ * console.log("按键按下");
1210
+ * })
1211
+ */
1212
+ keydown(
1213
+ target: HTMLElement | Window | typeof globalThis | string,
1214
+ handler: (event: DOMUtils_Event["keydown"]) => void,
1215
+ option?: boolean | AddEventListenerOptions
1216
+ ) {
1217
+ let DOMUtilsContext = this;
1218
+ if (target == null) {
1219
+ return;
1220
+ }
1221
+ if (typeof target === "string") {
1222
+ target = DOMUtilsContext.windowApi.document.querySelector(
1223
+ target
1224
+ ) as HTMLElement;
1225
+ }
1226
+ DOMUtilsContext.on(target, "keydown", null, handler, option);
1227
+ }
1228
+ /**
1229
+ * 当按键按下时触发事件
1230
+ * keydown - > keypress - > keyup
1231
+ * @param target 目标
1232
+ * @param handler 事件处理函数
1233
+ * @param option 配置
1234
+ * @example
1235
+ * // 监听a.xx元素的按键按下
1236
+ * DOMUtils.keypress(document.querySelector("a.xx"),()=>{
1237
+ * console.log("按键按下");
1238
+ * })
1239
+ * DOMUtils.keypress("a.xx",()=>{
1240
+ * console.log("按键按下");
1241
+ * })
1242
+ */
1243
+ keypress(
1244
+ target: HTMLElement | Window | typeof globalThis | string,
1245
+ handler: (event: DOMUtils_Event["keypress"]) => void,
1246
+ option?: boolean | AddEventListenerOptions
1247
+ ) {
1248
+ let DOMUtilsContext = this;
1249
+ if (target == null) {
1250
+ return;
1251
+ }
1252
+ if (typeof target === "string") {
1253
+ target = DOMUtilsContext.windowApi.document.querySelector(
1254
+ target
1255
+ ) as HTMLElement;
1256
+ }
1257
+ DOMUtilsContext.on(target, "keypress", null, handler, option);
1258
+ }
1259
+ }