-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrigger.ts
106 lines (90 loc) · 2.92 KB
/
trigger.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import * as utils from './utils';
import { $Cache, dispatch } from './delegate';
type InputProps =
'bubbles' | 'cancelable' | 'button' | 'buttons' | 'clientX' | 'clientY' |
'screenX' | 'screenY' | 'deltaX' | 'deltaY' | 'deltaZ' | 'deltaMode' | 'altKey' |
'code' | 'ctrlKey' | 'key' | 'location' | 'metaKey' | 'repeat' | 'shiftKey';
type AllEvent = Event & MouseEvent & KeyboardEvent & WheelEvent;
type PartialEvent = Partial<{ [key in InputProps]: AllEvent[key] } & { capture: boolean }>;
/**
* create a native event object
* @param {PartialEvent} option
* @returns {Event}
*/
function createEvent(type: string, option: PartialEvent) {
// default all mock events allow cancellation, allow bubbling
const opts = {
bubbles: true,
cancelable: true,
...option,
};
let evt;
if (/^mouse(?!wheel)|click/i.test(type)) {
evt = new MouseEvent(type, opts);
}
else if (/^key/i.test(type)) {
evt = new KeyboardEvent(type, opts);
}
else {
evt = new Event(type, opts);
}
return (evt);
}
/**
* set property value for event object
* @param {Event} evt
* @param {string} property
* @param {*} value
*/
function setEventProperty(evt: Event, property: string, value: any) {
Object.defineProperty(evt, property, { value, enumerable: true, writable: true });
}
/**
* triggers a delegate event
* @param {HTMLElement} elem
* @param {string} name
* @param {PartialEvent} [opts={}]
*/
export function triggerDelegateEvent(elem: HTMLElement, type: string, opts: PartialEvent = {}) {
if (elem.nodeType === 3 || elem.nodeType === 8) {
return;
}
// event phase
const capture = opts.capture ? 1 : 3;
delete opts.capture;
// assembly delegete dom path
const html = document.body.parentElement as HTMLElement;
const path: HTMLElement[] = [];
for (let i = elem; !utils.isNull(i.parentElement); i = i.parentElement) {
if ($Cache.has(i)) {
path.push(i);
}
}
$Cache.has(html) && path.push(html);
// create native event
const nativeEvent = createEvent(type, opts);
setEventProperty(nativeEvent, 'target', elem);
setEventProperty(nativeEvent, 'eventPhase', capture);
if (capture === 1) {
path.reverse();
}
path.forEach((dom) => {
setEventProperty(nativeEvent, 'currentTarget', dom);
// FIXME: Is it really possible to use the dispatch function directly here?
dispatch(dom, nativeEvent);
});
}
/**
* triggers a native event
* - the event of the delegate is also triggered during the execution of the event stream
* @param {HTMLElement} elem
* @param {string} name
* @param {PartialEvent} [opts={}]
*/
export function triggerEvent(elem: HTMLElement, type: string, opts: PartialEvent = {}) {
if (elem.nodeType === 3 || elem.nodeType === 8) {
return;
}
const evt = createEvent(type, opts);
elem.dispatchEvent(evt);
}