pseudo-dom 0.6.0 → 0.8.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.
- package/README.md +686 -241
- package/browser/pseudo-dom.js +3576 -735
- package/browser/pseudo-dom.min.js +1 -1
- package/dist/classes/PseudoEventListener.d.ts +96 -96
- package/dist/classes/PseudoEventListener.js +151 -151
- package/dist/classes/PseudoHTMLDocument.d.ts +17 -43
- package/dist/classes/PseudoHTMLDocument.js +24 -94
- package/dist/classes/PseudoHTMLDocument.min.js +1 -1
- package/dist/classes/PseudoNodeList.d.ts +34 -34
- package/dist/classes/PseudoNodeList.js +71 -71
- package/dist/factories/createEvent.d.ts +28 -28
- package/dist/factories/createEvent.js +56 -56
- package/dist/factories/cssSelectAdapter.d.ts +23 -0
- package/dist/factories/cssSelectAdapter.js +87 -0
- package/dist/factories/cssSelectAdapter.min.js +1 -0
- package/dist/factories/eventDefaults.d.ts +31 -31
- package/dist/factories/eventDefaults.js +105 -105
- package/dist/factories/generateDocument.d.ts +11 -11
- package/dist/factories/generateDocument.js +65 -65
- package/dist/factories/generateNodeList.d.ts +9 -9
- package/dist/factories/generateNodeList.js +13 -13
- package/dist/factories/query.d.ts +33 -0
- package/dist/factories/query.js +66 -0
- package/dist/factories/query.min.js +1 -0
- package/dist/functions/activeElement.d.ts +14 -14
- package/dist/functions/activeElement.js +33 -33
- package/dist/functions/getElementById.d.ts +13 -0
- package/dist/functions/getElementById.js +33 -0
- package/dist/functions/getElementById.min.js +1 -0
- package/dist/functions/getParentNodes.d.ts +11 -11
- package/dist/functions/getParentNodes.js +22 -22
- package/dist/functions/getParentNodesFromAttribute.d.ts +14 -14
- package/dist/functions/getParentNodesFromAttribute.js +29 -29
- package/dist/functions/modifierState.d.ts +29 -29
- package/dist/functions/modifierState.js +41 -41
- package/dist/interfaces/PseudoAnimation.d.ts +3 -3
- package/dist/interfaces/PseudoAnimation.js +5 -5
- package/dist/interfaces/PseudoAttr.d.ts +11 -11
- package/dist/interfaces/PseudoAttr.js +5 -5
- package/dist/interfaces/PseudoDOMTokenList.d.ts +16 -16
- package/dist/interfaces/PseudoDOMTokenList.js +5 -5
- package/dist/interfaces/PseudoDocument.d.ts +32 -0
- package/dist/interfaces/PseudoDocument.js +5 -5
- package/dist/interfaces/PseudoDocumentFragment.d.ts +7 -0
- package/dist/interfaces/PseudoDocumentFragment.js +5 -5
- package/dist/interfaces/PseudoElement.d.ts +702 -689
- package/dist/interfaces/PseudoElement.js +5 -5
- package/dist/interfaces/PseudoEvent.d.ts +79 -79
- package/dist/interfaces/PseudoEvent.js +10 -10
- package/dist/interfaces/PseudoEventTarget.d.ts +46 -46
- package/dist/interfaces/PseudoEventTarget.js +5 -5
- package/dist/interfaces/PseudoHTMLCollection.d.ts +23 -23
- package/dist/interfaces/PseudoHTMLCollection.js +5 -5
- package/dist/interfaces/PseudoHTMLElement.d.ts +22 -22
- package/dist/interfaces/PseudoHTMLElement.js +5 -5
- package/dist/interfaces/PseudoHTMLSlotElement.d.ts +3 -3
- package/dist/interfaces/PseudoHTMLSlotElement.js +5 -5
- package/dist/interfaces/PseudoNamedNodeMap.d.ts +11 -11
- package/dist/interfaces/PseudoNamedNodeMap.js +5 -5
- package/dist/interfaces/PseudoNode.d.ts +179 -179
- package/dist/interfaces/PseudoNode.js +5 -5
- package/dist/interfaces/PseudoShadowRoot.d.ts +3 -3
- package/dist/interfaces/PseudoShadowRoot.js +5 -5
- package/dist/main.d.ts +63 -63
- package/dist/main.js +155 -155
- package/dist/services/AnimationService.d.ts +4 -4
- package/dist/services/AnimationService.js +16 -16
- package/dist/services/AttrService.d.ts +37 -37
- package/dist/services/AttrService.js +81 -81
- package/dist/services/CommentService.d.ts +1 -1
- package/dist/services/CommentService.js +13 -13
- package/dist/services/CustomEventService.d.ts +37 -37
- package/dist/services/CustomEventService.js +35 -35
- package/dist/services/DOMTokenListService.d.ts +33 -33
- package/dist/services/DOMTokenListService.js +117 -117
- package/dist/services/DocumentFragmentService.d.ts +8 -0
- package/dist/services/DocumentFragmentService.js +18 -0
- package/dist/services/DocumentFragmentService.min.js +1 -1
- package/dist/services/DocumentService.d.ts +35 -1
- package/dist/services/DocumentService.js +72 -0
- package/dist/services/DocumentService.min.js +1 -1
- package/dist/services/ElementService.d.ts +191 -178
- package/dist/services/ElementService.js +426 -406
- package/dist/services/ElementService.min.js +1 -1
- package/dist/services/EventService.d.ts +120 -120
- package/dist/services/EventService.js +250 -250
- package/dist/services/EventTargetService.d.ts +84 -84
- package/dist/services/EventTargetService.js +232 -232
- package/dist/services/FocusEventService.d.ts +32 -32
- package/dist/services/FocusEventService.js +35 -35
- package/dist/services/HTMLCollectionService.d.ts +54 -49
- package/dist/services/HTMLCollectionService.js +92 -75
- package/dist/services/HTMLCollectionService.min.js +1 -1
- package/dist/services/HTMLElementService.d.ts +57 -57
- package/dist/services/HTMLElementService.js +163 -163
- package/dist/services/HTMLSlotElementService.d.ts +4 -4
- package/dist/services/HTMLSlotElementService.js +9 -9
- package/dist/services/InputEventService.d.ts +41 -41
- package/dist/services/InputEventService.js +47 -47
- package/dist/services/KeyboardEventService.d.ts +70 -70
- package/dist/services/KeyboardEventService.js +86 -86
- package/dist/services/MouseEventService.d.ts +80 -80
- package/dist/services/MouseEventService.js +108 -108
- package/dist/services/NamedNodeMapService.d.ts +23 -23
- package/dist/services/NamedNodeMapService.js +77 -77
- package/dist/services/NodeService.d.ts +297 -271
- package/dist/services/NodeService.js +721 -679
- package/dist/services/NodeService.min.js +1 -1
- package/dist/services/PointerEventService.d.ts +51 -51
- package/dist/services/PointerEventService.js +67 -67
- package/dist/services/ShadowRootService.d.ts +4 -4
- package/dist/services/ShadowRootService.js +9 -9
- package/dist/services/TextService.d.ts +1 -1
- package/dist/services/TextService.js +13 -13
- package/dist/services/UIEventService.d.ts +43 -43
- package/dist/services/UIEventService.js +42 -42
- package/dist/simulate.d.ts +32 -32
- package/dist/simulate.js +115 -115
- package/package.json +4 -3
- package/dist/classes.d.ts +0 -20
- package/dist/classes.js +0 -31
- package/dist/classes.min.js +0 -1
- package/dist/factories/generateNode.d.ts +0 -32
- package/dist/factories/generateNode.js +0 -85
- package/dist/factories/generateNode.min.js +0 -1
- package/dist/factories.d.ts +0 -11
- package/dist/factories.js +0 -27
- package/dist/factories.min.js +0 -1
- package/dist/functions.d.ts +0 -5
- package/dist/functions.js +0 -23
- package/dist/functions.min.js +0 -1
|
@@ -1,232 +1,232 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
require('core-js/modules/esnext.iterator.constructor.js')
|
|
4
|
-
require('core-js/modules/esnext.iterator.filter.js')
|
|
5
|
-
require('core-js/modules/esnext.iterator.find.js')
|
|
6
|
-
require('core-js/modules/esnext.iterator.for-each.js')
|
|
7
|
-
require('core-js/modules/esnext.iterator.map.js')
|
|
8
|
-
require('core-js/modules/esnext.iterator.some.js')
|
|
9
|
-
const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
10
|
-
return mod && mod.__esModule
|
|
11
|
-
? mod
|
|
12
|
-
: {
|
|
13
|
-
default: mod
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
Object.defineProperty(exports, '__esModule', {
|
|
17
|
-
value: true
|
|
18
|
-
})
|
|
19
|
-
/**
|
|
20
|
-
* @file Substitute for the DOM EventTarget Class.
|
|
21
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
22
|
-
* @version 1.0.0
|
|
23
|
-
*/
|
|
24
|
-
const EventService_1 = require('./EventService')
|
|
25
|
-
const PseudoEventListener_1 = __importDefault(require('../classes/PseudoEventListener'))
|
|
26
|
-
const getParentNodes_1 = __importDefault(require('../functions/getParentNodes'))
|
|
27
|
-
const LinkedList_1 = require('collect-your-stuff/dist/collections/linked-list/LinkedList')
|
|
28
|
-
/**
|
|
29
|
-
* Simulate the behaviour of the EventTarget Class when there is no DOM available.
|
|
30
|
-
* Dispatching an event sends it through the tree the way the DOM does: down from the root to the target (capture
|
|
31
|
-
* listeners), to the target itself, then back up to the root (the listeners which are not capture listeners, when the
|
|
32
|
-
* event bubbles).
|
|
33
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
34
|
-
* @class
|
|
35
|
-
* @property {Object.<string, Array.<PseudoEventListener>>} listeners
|
|
36
|
-
* @property {function} addEventListener
|
|
37
|
-
* @property {function} removeEventListener
|
|
38
|
-
* @property {function} dispatchEvent
|
|
39
|
-
*/
|
|
40
|
-
class EventTargetService {
|
|
41
|
-
/**
|
|
42
|
-
* @constructor
|
|
43
|
-
*/
|
|
44
|
-
constructor () {
|
|
45
|
-
this.listeners = {}
|
|
46
|
-
this.defaultEvent = {}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* The listeners registered for a type of event, creating the (empty) list of them when there are none yet.
|
|
51
|
-
* @param {string} type
|
|
52
|
-
* @returns {LinkedList}
|
|
53
|
-
*/
|
|
54
|
-
listenersFor (type) {
|
|
55
|
-
if (!(type in this.listeners)) {
|
|
56
|
-
this.listeners[type] = new LinkedList_1.LinkedList()
|
|
57
|
-
}
|
|
58
|
-
return this.listeners[type]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Run the listeners registered on this target for the type of the event which apply to the phase the event is in
|
|
63
|
-
* (at the target, the capture listeners run before the others). Listeners which are added while this runs do not run
|
|
64
|
-
* for this event, and listeners which are removed while it runs no longer do. Running stops as soon as immediate
|
|
65
|
-
* propagation is stopped. A listener which throws does not stop the others.
|
|
66
|
-
* @param {EventService} event The event, which is at a phase and has a current target
|
|
67
|
-
* @returns {Array<*>} The errors which the listeners threw
|
|
68
|
-
*/
|
|
69
|
-
runEvents (event) {
|
|
70
|
-
const errors = []
|
|
71
|
-
if (!(event.type in this.listeners)) {
|
|
72
|
-
return errors
|
|
73
|
-
}
|
|
74
|
-
const listeners = Array.from(this.listeners[event.type]).map(linker => linker.data)
|
|
75
|
-
// At the target the capture listeners come first, otherwise the order is the order they were added
|
|
76
|
-
const ordered = event.eventPhase === EventService_1.EventService.AT_TARGET ? listeners.filter(listener => listener.capture).concat(listeners.filter(listener => !listener.capture)) : listeners
|
|
77
|
-
for (const listener of ordered) {
|
|
78
|
-
if (event.inner.immediatePropagationStopped) {
|
|
79
|
-
break
|
|
80
|
-
}
|
|
81
|
-
if (listener.rejectEvent(event)) {
|
|
82
|
-
continue
|
|
83
|
-
}
|
|
84
|
-
if (listener.once) {
|
|
85
|
-
this.removeListener(event.type, listener)
|
|
86
|
-
}
|
|
87
|
-
event.inner.inPassiveListener = listener.passive
|
|
88
|
-
try {
|
|
89
|
-
listener.handleEvent(event)
|
|
90
|
-
} catch (error) {
|
|
91
|
-
errors.push(error)
|
|
92
|
-
}
|
|
93
|
-
event.inner.inPassiveListener = false
|
|
94
|
-
}
|
|
95
|
-
return errors
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Take a listener out of the registered listeners, so that it does not run again.
|
|
100
|
-
* @param {string} type
|
|
101
|
-
* @param {PseudoEventListener} listener
|
|
102
|
-
*/
|
|
103
|
-
removeListener (type, listener) {
|
|
104
|
-
listener.removed = true
|
|
105
|
-
const registered = this.listeners[type]
|
|
106
|
-
Array.from(registered).filter(linker => linker.data === listener).forEach(linker => registered.remove(linker))
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Register the function to run when nothing else has prevented the default for this type of event.
|
|
111
|
-
* @param {string} type
|
|
112
|
-
* @param {Function} callback
|
|
113
|
-
*/
|
|
114
|
-
setDefaultEvent (type, callback) {
|
|
115
|
-
this.listenersFor(type)
|
|
116
|
-
this.defaultEvent[type] = callback
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Registers an event handler of a specific event type. Adding the same handler again for the same type and phase does
|
|
121
|
-
* nothing, like the DOM.
|
|
122
|
-
* @param {string} type The type of event to listen for
|
|
123
|
-
* @param {Function|Object} callback The function to call (or an object with a handleEvent function)
|
|
124
|
-
* @param {Object|boolean} [useCapture=false] Listen while the event travels down to the target (true), or an object with capture, once and passive
|
|
125
|
-
*/
|
|
126
|
-
addEventListener (type, callback, useCapture = false) {
|
|
127
|
-
let options = {
|
|
128
|
-
capture: false,
|
|
129
|
-
once: false,
|
|
130
|
-
passive: false
|
|
131
|
-
}
|
|
132
|
-
if (typeof useCapture === 'object' && useCapture !== null) {
|
|
133
|
-
// Originally useCapture was a single boolean flag, later optional other flags can be used
|
|
134
|
-
// Here we take all the given flags from the object and assign them as the options
|
|
135
|
-
options = Object.assign(options, useCapture)
|
|
136
|
-
} else {
|
|
137
|
-
options.capture = !!useCapture
|
|
138
|
-
}
|
|
139
|
-
const listeners = this.listenersFor(type)
|
|
140
|
-
const alreadyAdded = Array.from(listeners).some(linker => linker.data.callback === callback && linker.data.capture === options.capture)
|
|
141
|
-
if (alreadyAdded) {
|
|
142
|
-
return
|
|
143
|
-
}
|
|
144
|
-
// A function runs with this target as this, an object runs its handleEvent as itself
|
|
145
|
-
const handler = typeof callback === 'function' ? callback.bind(this) : callback.handleEvent.bind(callback)
|
|
146
|
-
const listener = new PseudoEventListener_1.default(type, options, handler, callback)
|
|
147
|
-
// Listeners run in the order they were added, except that listeners which are not defaults always come before the defaults
|
|
148
|
-
const firstDefault = Array.from(listeners).find(linker => linker.data.isDefault)
|
|
149
|
-
if (firstDefault && !listener.isDefault) {
|
|
150
|
-
listeners.insertBefore(firstDefault, listener)
|
|
151
|
-
} else {
|
|
152
|
-
listeners.append(listener)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Removes an event listener, the one which was added with the same type, handler and phase.
|
|
158
|
-
* @param {string} type The type of event
|
|
159
|
-
* @param {Function|Object} callback The handler which was added
|
|
160
|
-
* @param {Object|boolean} [options=false] Whether the listener was a capture listener (true), or an object with capture
|
|
161
|
-
*/
|
|
162
|
-
removeEventListener (type, callback, options = false) {
|
|
163
|
-
if (!(type in this.listeners)) {
|
|
164
|
-
return
|
|
165
|
-
}
|
|
166
|
-
const capture = typeof options === 'object' && options !== null ? !!options.capture : !!options
|
|
167
|
-
Array.from(this.listeners[type]).map(linker => linker.data).filter(listener => !listener.isDefault && listener.callback === callback && listener.capture === capture).forEach(listener => this.removeListener(type, listener))
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Dispatches an event to this target and through the tree: capture listeners of the ancestors from the root down,
|
|
172
|
-
* then the listeners of this target, then (when the event bubbles) the other listeners of the ancestors from the
|
|
173
|
-
* parent up to the root. stopPropagation() stops it reaching further targets, stopImmediatePropagation() also stops
|
|
174
|
-
* the remaining listeners of the current target. Afterwards, unless the default was prevented, the default action
|
|
175
|
-
* of this target (see setDefaultEvent) runs. The event can be dispatched again afterwards.
|
|
176
|
-
* @param {EventService} event The event to dispatch
|
|
177
|
-
* @returns {boolean} False when the event was cancelable and a listener prevented the default, otherwise true
|
|
178
|
-
* @throws {Error} When the event is already being dispatched, or (after the whole dispatch has finished) the error
|
|
179
|
-
* which a listener threw (an error with all of them in its errors property when several did)
|
|
180
|
-
*/
|
|
181
|
-
dispatchEvent (event) {
|
|
182
|
-
if (event.inner.dispatching) {
|
|
183
|
-
throw new Error('The event is already being dispatched.')
|
|
184
|
-
}
|
|
185
|
-
event.inner.dispatching = true
|
|
186
|
-
event.inner.target = this
|
|
187
|
-
// The ancestors, the root first, which can have listeners
|
|
188
|
-
const ancestors = (0, getParentNodes_1.default)(this).filter(node => node instanceof EventTargetService)
|
|
189
|
-
event.inner.path = [this].concat(ancestors.slice().reverse())
|
|
190
|
-
const errors = []
|
|
191
|
-
const visit = (target, phase) => {
|
|
192
|
-
event.inner.eventPhase = phase
|
|
193
|
-
event.inner.currentTarget = target
|
|
194
|
-
errors.push(...target.runEvents(event))
|
|
195
|
-
}
|
|
196
|
-
for (const ancestor of ancestors) {
|
|
197
|
-
if (event.inner.propagationStopped) {
|
|
198
|
-
break
|
|
199
|
-
}
|
|
200
|
-
visit(ancestor, EventService_1.EventService.CAPTURING_PHASE)
|
|
201
|
-
}
|
|
202
|
-
if (!event.inner.propagationStopped) {
|
|
203
|
-
visit(this, EventService_1.EventService.AT_TARGET)
|
|
204
|
-
}
|
|
205
|
-
if (event.bubbles) {
|
|
206
|
-
for (const ancestor of ancestors.slice().reverse()) {
|
|
207
|
-
if (event.inner.propagationStopped) {
|
|
208
|
-
break
|
|
209
|
-
}
|
|
210
|
-
visit(ancestor, EventService_1.EventService.BUBBLING_PHASE)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
event.inner.finishDispatch()
|
|
214
|
-
if (!event.defaultPrevented && typeof this.defaultEvent[event.type] === 'function') {
|
|
215
|
-
try {
|
|
216
|
-
this.defaultEvent[event.type](event)
|
|
217
|
-
} catch (error) {
|
|
218
|
-
errors.push(error)
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (errors.length === 1) {
|
|
222
|
-
throw errors[0]
|
|
223
|
-
}
|
|
224
|
-
if (errors.length > 1) {
|
|
225
|
-
throw Object.assign(new Error(`${errors.length} listeners threw an error while dispatching the ${event.type} event.`), {
|
|
226
|
-
errors
|
|
227
|
-
})
|
|
228
|
-
}
|
|
229
|
-
return !event.defaultPrevented
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
exports.default = EventTargetService
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
require('core-js/modules/esnext.iterator.constructor.js')
|
|
4
|
+
require('core-js/modules/esnext.iterator.filter.js')
|
|
5
|
+
require('core-js/modules/esnext.iterator.find.js')
|
|
6
|
+
require('core-js/modules/esnext.iterator.for-each.js')
|
|
7
|
+
require('core-js/modules/esnext.iterator.map.js')
|
|
8
|
+
require('core-js/modules/esnext.iterator.some.js')
|
|
9
|
+
const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
10
|
+
return mod && mod.__esModule
|
|
11
|
+
? mod
|
|
12
|
+
: {
|
|
13
|
+
default: mod
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
})
|
|
19
|
+
/**
|
|
20
|
+
* @file Substitute for the DOM EventTarget Class.
|
|
21
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
22
|
+
* @version 1.0.0
|
|
23
|
+
*/
|
|
24
|
+
const EventService_1 = require('./EventService')
|
|
25
|
+
const PseudoEventListener_1 = __importDefault(require('../classes/PseudoEventListener'))
|
|
26
|
+
const getParentNodes_1 = __importDefault(require('../functions/getParentNodes'))
|
|
27
|
+
const LinkedList_1 = require('collect-your-stuff/dist/collections/linked-list/LinkedList')
|
|
28
|
+
/**
|
|
29
|
+
* Simulate the behaviour of the EventTarget Class when there is no DOM available.
|
|
30
|
+
* Dispatching an event sends it through the tree the way the DOM does: down from the root to the target (capture
|
|
31
|
+
* listeners), to the target itself, then back up to the root (the listeners which are not capture listeners, when the
|
|
32
|
+
* event bubbles).
|
|
33
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
34
|
+
* @class
|
|
35
|
+
* @property {Object.<string, Array.<PseudoEventListener>>} listeners
|
|
36
|
+
* @property {function} addEventListener
|
|
37
|
+
* @property {function} removeEventListener
|
|
38
|
+
* @property {function} dispatchEvent
|
|
39
|
+
*/
|
|
40
|
+
class EventTargetService {
|
|
41
|
+
/**
|
|
42
|
+
* @constructor
|
|
43
|
+
*/
|
|
44
|
+
constructor () {
|
|
45
|
+
this.listeners = {}
|
|
46
|
+
this.defaultEvent = {}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The listeners registered for a type of event, creating the (empty) list of them when there are none yet.
|
|
51
|
+
* @param {string} type
|
|
52
|
+
* @returns {LinkedList}
|
|
53
|
+
*/
|
|
54
|
+
listenersFor (type) {
|
|
55
|
+
if (!(type in this.listeners)) {
|
|
56
|
+
this.listeners[type] = new LinkedList_1.LinkedList()
|
|
57
|
+
}
|
|
58
|
+
return this.listeners[type]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Run the listeners registered on this target for the type of the event which apply to the phase the event is in
|
|
63
|
+
* (at the target, the capture listeners run before the others). Listeners which are added while this runs do not run
|
|
64
|
+
* for this event, and listeners which are removed while it runs no longer do. Running stops as soon as immediate
|
|
65
|
+
* propagation is stopped. A listener which throws does not stop the others.
|
|
66
|
+
* @param {EventService} event The event, which is at a phase and has a current target
|
|
67
|
+
* @returns {Array<*>} The errors which the listeners threw
|
|
68
|
+
*/
|
|
69
|
+
runEvents (event) {
|
|
70
|
+
const errors = []
|
|
71
|
+
if (!(event.type in this.listeners)) {
|
|
72
|
+
return errors
|
|
73
|
+
}
|
|
74
|
+
const listeners = Array.from(this.listeners[event.type]).map(linker => linker.data)
|
|
75
|
+
// At the target the capture listeners come first, otherwise the order is the order they were added
|
|
76
|
+
const ordered = event.eventPhase === EventService_1.EventService.AT_TARGET ? listeners.filter(listener => listener.capture).concat(listeners.filter(listener => !listener.capture)) : listeners
|
|
77
|
+
for (const listener of ordered) {
|
|
78
|
+
if (event.inner.immediatePropagationStopped) {
|
|
79
|
+
break
|
|
80
|
+
}
|
|
81
|
+
if (listener.rejectEvent(event)) {
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
if (listener.once) {
|
|
85
|
+
this.removeListener(event.type, listener)
|
|
86
|
+
}
|
|
87
|
+
event.inner.inPassiveListener = listener.passive
|
|
88
|
+
try {
|
|
89
|
+
listener.handleEvent(event)
|
|
90
|
+
} catch (error) {
|
|
91
|
+
errors.push(error)
|
|
92
|
+
}
|
|
93
|
+
event.inner.inPassiveListener = false
|
|
94
|
+
}
|
|
95
|
+
return errors
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Take a listener out of the registered listeners, so that it does not run again.
|
|
100
|
+
* @param {string} type
|
|
101
|
+
* @param {PseudoEventListener} listener
|
|
102
|
+
*/
|
|
103
|
+
removeListener (type, listener) {
|
|
104
|
+
listener.removed = true
|
|
105
|
+
const registered = this.listeners[type]
|
|
106
|
+
Array.from(registered).filter(linker => linker.data === listener).forEach(linker => registered.remove(linker))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Register the function to run when nothing else has prevented the default for this type of event.
|
|
111
|
+
* @param {string} type
|
|
112
|
+
* @param {Function} callback
|
|
113
|
+
*/
|
|
114
|
+
setDefaultEvent (type, callback) {
|
|
115
|
+
this.listenersFor(type)
|
|
116
|
+
this.defaultEvent[type] = callback
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Registers an event handler of a specific event type. Adding the same handler again for the same type and phase does
|
|
121
|
+
* nothing, like the DOM.
|
|
122
|
+
* @param {string} type The type of event to listen for
|
|
123
|
+
* @param {Function|Object} callback The function to call (or an object with a handleEvent function)
|
|
124
|
+
* @param {Object|boolean} [useCapture=false] Listen while the event travels down to the target (true), or an object with capture, once and passive
|
|
125
|
+
*/
|
|
126
|
+
addEventListener (type, callback, useCapture = false) {
|
|
127
|
+
let options = {
|
|
128
|
+
capture: false,
|
|
129
|
+
once: false,
|
|
130
|
+
passive: false
|
|
131
|
+
}
|
|
132
|
+
if (typeof useCapture === 'object' && useCapture !== null) {
|
|
133
|
+
// Originally useCapture was a single boolean flag, later optional other flags can be used
|
|
134
|
+
// Here we take all the given flags from the object and assign them as the options
|
|
135
|
+
options = Object.assign(options, useCapture)
|
|
136
|
+
} else {
|
|
137
|
+
options.capture = !!useCapture
|
|
138
|
+
}
|
|
139
|
+
const listeners = this.listenersFor(type)
|
|
140
|
+
const alreadyAdded = Array.from(listeners).some(linker => linker.data.callback === callback && linker.data.capture === options.capture)
|
|
141
|
+
if (alreadyAdded) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
// A function runs with this target as this, an object runs its handleEvent as itself
|
|
145
|
+
const handler = typeof callback === 'function' ? callback.bind(this) : callback.handleEvent.bind(callback)
|
|
146
|
+
const listener = new PseudoEventListener_1.default(type, options, handler, callback)
|
|
147
|
+
// Listeners run in the order they were added, except that listeners which are not defaults always come before the defaults
|
|
148
|
+
const firstDefault = Array.from(listeners).find(linker => linker.data.isDefault)
|
|
149
|
+
if (firstDefault && !listener.isDefault) {
|
|
150
|
+
listeners.insertBefore(firstDefault, listener)
|
|
151
|
+
} else {
|
|
152
|
+
listeners.append(listener)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Removes an event listener, the one which was added with the same type, handler and phase.
|
|
158
|
+
* @param {string} type The type of event
|
|
159
|
+
* @param {Function|Object} callback The handler which was added
|
|
160
|
+
* @param {Object|boolean} [options=false] Whether the listener was a capture listener (true), or an object with capture
|
|
161
|
+
*/
|
|
162
|
+
removeEventListener (type, callback, options = false) {
|
|
163
|
+
if (!(type in this.listeners)) {
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
const capture = typeof options === 'object' && options !== null ? !!options.capture : !!options
|
|
167
|
+
Array.from(this.listeners[type]).map(linker => linker.data).filter(listener => !listener.isDefault && listener.callback === callback && listener.capture === capture).forEach(listener => this.removeListener(type, listener))
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Dispatches an event to this target and through the tree: capture listeners of the ancestors from the root down,
|
|
172
|
+
* then the listeners of this target, then (when the event bubbles) the other listeners of the ancestors from the
|
|
173
|
+
* parent up to the root. stopPropagation() stops it reaching further targets, stopImmediatePropagation() also stops
|
|
174
|
+
* the remaining listeners of the current target. Afterwards, unless the default was prevented, the default action
|
|
175
|
+
* of this target (see setDefaultEvent) runs. The event can be dispatched again afterwards.
|
|
176
|
+
* @param {EventService} event The event to dispatch
|
|
177
|
+
* @returns {boolean} False when the event was cancelable and a listener prevented the default, otherwise true
|
|
178
|
+
* @throws {Error} When the event is already being dispatched, or (after the whole dispatch has finished) the error
|
|
179
|
+
* which a listener threw (an error with all of them in its errors property when several did)
|
|
180
|
+
*/
|
|
181
|
+
dispatchEvent (event) {
|
|
182
|
+
if (event.inner.dispatching) {
|
|
183
|
+
throw new Error('The event is already being dispatched.')
|
|
184
|
+
}
|
|
185
|
+
event.inner.dispatching = true
|
|
186
|
+
event.inner.target = this
|
|
187
|
+
// The ancestors, the root first, which can have listeners
|
|
188
|
+
const ancestors = (0, getParentNodes_1.default)(this).filter(node => node instanceof EventTargetService)
|
|
189
|
+
event.inner.path = [this].concat(ancestors.slice().reverse())
|
|
190
|
+
const errors = []
|
|
191
|
+
const visit = (target, phase) => {
|
|
192
|
+
event.inner.eventPhase = phase
|
|
193
|
+
event.inner.currentTarget = target
|
|
194
|
+
errors.push(...target.runEvents(event))
|
|
195
|
+
}
|
|
196
|
+
for (const ancestor of ancestors) {
|
|
197
|
+
if (event.inner.propagationStopped) {
|
|
198
|
+
break
|
|
199
|
+
}
|
|
200
|
+
visit(ancestor, EventService_1.EventService.CAPTURING_PHASE)
|
|
201
|
+
}
|
|
202
|
+
if (!event.inner.propagationStopped) {
|
|
203
|
+
visit(this, EventService_1.EventService.AT_TARGET)
|
|
204
|
+
}
|
|
205
|
+
if (event.bubbles) {
|
|
206
|
+
for (const ancestor of ancestors.slice().reverse()) {
|
|
207
|
+
if (event.inner.propagationStopped) {
|
|
208
|
+
break
|
|
209
|
+
}
|
|
210
|
+
visit(ancestor, EventService_1.EventService.BUBBLING_PHASE)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
event.inner.finishDispatch()
|
|
214
|
+
if (!event.defaultPrevented && typeof this.defaultEvent[event.type] === 'function') {
|
|
215
|
+
try {
|
|
216
|
+
this.defaultEvent[event.type](event)
|
|
217
|
+
} catch (error) {
|
|
218
|
+
errors.push(error)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (errors.length === 1) {
|
|
222
|
+
throw errors[0]
|
|
223
|
+
}
|
|
224
|
+
if (errors.length > 1) {
|
|
225
|
+
throw Object.assign(new Error(`${errors.length} listeners threw an error while dispatching the ${event.type} event.`), {
|
|
226
|
+
errors
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
return !event.defaultPrevented
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
exports.default = EventTargetService
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Substitute for the DOM FocusEvent Class.
|
|
3
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
-
* @version 1.0.0
|
|
5
|
-
*/
|
|
6
|
-
import { UIEventInit, UIEventService } from './UIEventService';
|
|
7
|
-
import { PseudoEventTarget } from '../interfaces/PseudoEventTarget';
|
|
8
|
-
/**
|
|
9
|
-
* The options for creating a focus event, on top of the ones every UI event has.
|
|
10
|
-
* @typedef {Object} FocusEventInit
|
|
11
|
-
* @property {PseudoEventTarget|null} [relatedTarget=null] The other target involved (the one losing or gaining the focus)
|
|
12
|
-
*/
|
|
13
|
-
export type FocusEventInit = UIEventInit & {
|
|
14
|
-
relatedTarget?: PseudoEventTarget | null;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Simulate the behaviour of the FocusEvent Class when there is no DOM available.
|
|
18
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
19
|
-
* @class
|
|
20
|
-
* @augments UIEventService
|
|
21
|
-
* @property {PseudoEventTarget|null} relatedTarget
|
|
22
|
-
*/
|
|
23
|
-
export declare class FocusEventService extends UIEventService {
|
|
24
|
-
private readonly related;
|
|
25
|
-
/**
|
|
26
|
-
* @param {string} [typeArg=''] The type of the event
|
|
27
|
-
* @param {FocusEventInit} [init={}] The options for the event
|
|
28
|
-
* @constructor
|
|
29
|
-
*/
|
|
30
|
-
constructor(typeArg?: string, init?: FocusEventInit);
|
|
31
|
-
get relatedTarget(): PseudoEventTarget | null;
|
|
32
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file Substitute for the DOM FocusEvent Class.
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import { UIEventInit, UIEventService } from './UIEventService';
|
|
7
|
+
import { PseudoEventTarget } from '../interfaces/PseudoEventTarget';
|
|
8
|
+
/**
|
|
9
|
+
* The options for creating a focus event, on top of the ones every UI event has.
|
|
10
|
+
* @typedef {Object} FocusEventInit
|
|
11
|
+
* @property {PseudoEventTarget|null} [relatedTarget=null] The other target involved (the one losing or gaining the focus)
|
|
12
|
+
*/
|
|
13
|
+
export type FocusEventInit = UIEventInit & {
|
|
14
|
+
relatedTarget?: PseudoEventTarget | null;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Simulate the behaviour of the FocusEvent Class when there is no DOM available.
|
|
18
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
19
|
+
* @class
|
|
20
|
+
* @augments UIEventService
|
|
21
|
+
* @property {PseudoEventTarget|null} relatedTarget
|
|
22
|
+
*/
|
|
23
|
+
export declare class FocusEventService extends UIEventService {
|
|
24
|
+
private readonly related;
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} [typeArg=''] The type of the event
|
|
27
|
+
* @param {FocusEventInit} [init={}] The options for the event
|
|
28
|
+
* @constructor
|
|
29
|
+
*/
|
|
30
|
+
constructor(typeArg?: string, init?: FocusEventInit);
|
|
31
|
+
get relatedTarget(): PseudoEventTarget | null;
|
|
32
|
+
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', {
|
|
4
|
-
value: true
|
|
5
|
-
})
|
|
6
|
-
exports.FocusEventService = void 0
|
|
7
|
-
/**
|
|
8
|
-
* @file Substitute for the DOM FocusEvent Class.
|
|
9
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
10
|
-
* @version 1.0.0
|
|
11
|
-
*/
|
|
12
|
-
const UIEventService_1 = require('./UIEventService')
|
|
13
|
-
/**
|
|
14
|
-
* Simulate the behaviour of the FocusEvent Class when there is no DOM available.
|
|
15
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
16
|
-
* @class
|
|
17
|
-
* @augments UIEventService
|
|
18
|
-
* @property {PseudoEventTarget|null} relatedTarget
|
|
19
|
-
*/
|
|
20
|
-
class FocusEventService extends UIEventService_1.UIEventService {
|
|
21
|
-
/**
|
|
22
|
-
* @param {string} [typeArg=''] The type of the event
|
|
23
|
-
* @param {FocusEventInit} [init={}] The options for the event
|
|
24
|
-
* @constructor
|
|
25
|
-
*/
|
|
26
|
-
constructor (typeArg = '', init = {}) {
|
|
27
|
-
super(typeArg, init)
|
|
28
|
-
this.related = init.relatedTarget || null
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get relatedTarget () {
|
|
32
|
-
return this.related
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
exports.FocusEventService = FocusEventService
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
exports.FocusEventService = void 0
|
|
7
|
+
/**
|
|
8
|
+
* @file Substitute for the DOM FocusEvent Class.
|
|
9
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
const UIEventService_1 = require('./UIEventService')
|
|
13
|
+
/**
|
|
14
|
+
* Simulate the behaviour of the FocusEvent Class when there is no DOM available.
|
|
15
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
16
|
+
* @class
|
|
17
|
+
* @augments UIEventService
|
|
18
|
+
* @property {PseudoEventTarget|null} relatedTarget
|
|
19
|
+
*/
|
|
20
|
+
class FocusEventService extends UIEventService_1.UIEventService {
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} [typeArg=''] The type of the event
|
|
23
|
+
* @param {FocusEventInit} [init={}] The options for the event
|
|
24
|
+
* @constructor
|
|
25
|
+
*/
|
|
26
|
+
constructor (typeArg = '', init = {}) {
|
|
27
|
+
super(typeArg, init)
|
|
28
|
+
this.related = init.relatedTarget || null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get relatedTarget () {
|
|
32
|
+
return this.related
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.FocusEventService = FocusEventService
|