-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathtrusted-dispatch-event.ts
108 lines (95 loc) · 2.8 KB
/
trusted-dispatch-event.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
107
108
import { hit } from '../helpers';
import { type Source } from './scriptlets';
/**
* @trustedScriptlet trusted-dispatch-event
*
* @description
* Dispatches a custom event on a specified target.
*
* ### Syntax
*
* ```text
* example.org#%#//scriptlet('trusted-dispatch-event', event[, target])
* ```
*
* - `event` — required, name of the event to dispatch
* - `target` — optional, target on which event will be invoked. Possible values:
* - CSS selector — dispatch event on the element with the specified selector
* - `window` — dispatch event on the window object
* - if not set, then "document" is used — it's default value
*
* ### Examples
*
* 1. Dispatches a custom event "click" on the document.
*
* ```adblock
* example.org#%#//scriptlet('trusted-dispatch-event', 'click')
* ```
*
* 2. Dispatches a custom event "submit" on the element with the class "test".
*
* ```adblock
* example.org#%#//scriptlet('trusted-dispatch-event', 'submit', '.test')
* ```
*
* 3. Dispatches a custom event "load" on the window object.
*
* ```adblock
* example.org#%#//scriptlet('trusted-dispatch-event', 'load', 'window')
* ```
*
* @added v1.11.1.
*/
export function trustedDispatchEvent(
source: Source,
event: string,
target: string,
) {
if (!event) {
return;
}
let hasBeenDispatched = false;
let eventTarget: typeof window | Document | Element | null = document;
if (target === 'window') {
eventTarget = window;
}
const events = new Set<string>();
const dispatch = () => {
const customEvent = new Event(event);
if (typeof target === 'string' && target !== 'window') {
eventTarget = document.querySelector(target);
}
const isEventAdded = events.has(event);
if (!hasBeenDispatched && isEventAdded && eventTarget) {
hasBeenDispatched = true;
hit(source);
eventTarget.dispatchEvent(customEvent);
}
};
const wrapper = (
eventListener: typeof EventTarget.prototype.addEventListener,
thisArg: Element,
args: string[],
) => {
const eventName = args[0];
if (thisArg && eventName) {
events.add(eventName);
setTimeout(() => {
dispatch();
}, 1);
}
return Reflect.apply(eventListener, thisArg, args);
};
const handler = {
apply: wrapper,
};
EventTarget.prototype.addEventListener = new Proxy(EventTarget.prototype.addEventListener, handler);
}
export const trustedDispatchEventNames = [
'trusted-dispatch-event',
];
// eslint-disable-next-line prefer-destructuring
trustedDispatchEvent.primaryName = trustedDispatchEventNames[0];
trustedDispatchEvent.injections = [
hit,
];