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.
Files changed (131) hide show
  1. package/README.md +686 -241
  2. package/browser/pseudo-dom.js +3576 -735
  3. package/browser/pseudo-dom.min.js +1 -1
  4. package/dist/classes/PseudoEventListener.d.ts +96 -96
  5. package/dist/classes/PseudoEventListener.js +151 -151
  6. package/dist/classes/PseudoHTMLDocument.d.ts +17 -43
  7. package/dist/classes/PseudoHTMLDocument.js +24 -94
  8. package/dist/classes/PseudoHTMLDocument.min.js +1 -1
  9. package/dist/classes/PseudoNodeList.d.ts +34 -34
  10. package/dist/classes/PseudoNodeList.js +71 -71
  11. package/dist/factories/createEvent.d.ts +28 -28
  12. package/dist/factories/createEvent.js +56 -56
  13. package/dist/factories/cssSelectAdapter.d.ts +23 -0
  14. package/dist/factories/cssSelectAdapter.js +87 -0
  15. package/dist/factories/cssSelectAdapter.min.js +1 -0
  16. package/dist/factories/eventDefaults.d.ts +31 -31
  17. package/dist/factories/eventDefaults.js +105 -105
  18. package/dist/factories/generateDocument.d.ts +11 -11
  19. package/dist/factories/generateDocument.js +65 -65
  20. package/dist/factories/generateNodeList.d.ts +9 -9
  21. package/dist/factories/generateNodeList.js +13 -13
  22. package/dist/factories/query.d.ts +33 -0
  23. package/dist/factories/query.js +66 -0
  24. package/dist/factories/query.min.js +1 -0
  25. package/dist/functions/activeElement.d.ts +14 -14
  26. package/dist/functions/activeElement.js +33 -33
  27. package/dist/functions/getElementById.d.ts +13 -0
  28. package/dist/functions/getElementById.js +33 -0
  29. package/dist/functions/getElementById.min.js +1 -0
  30. package/dist/functions/getParentNodes.d.ts +11 -11
  31. package/dist/functions/getParentNodes.js +22 -22
  32. package/dist/functions/getParentNodesFromAttribute.d.ts +14 -14
  33. package/dist/functions/getParentNodesFromAttribute.js +29 -29
  34. package/dist/functions/modifierState.d.ts +29 -29
  35. package/dist/functions/modifierState.js +41 -41
  36. package/dist/interfaces/PseudoAnimation.d.ts +3 -3
  37. package/dist/interfaces/PseudoAnimation.js +5 -5
  38. package/dist/interfaces/PseudoAttr.d.ts +11 -11
  39. package/dist/interfaces/PseudoAttr.js +5 -5
  40. package/dist/interfaces/PseudoDOMTokenList.d.ts +16 -16
  41. package/dist/interfaces/PseudoDOMTokenList.js +5 -5
  42. package/dist/interfaces/PseudoDocument.d.ts +32 -0
  43. package/dist/interfaces/PseudoDocument.js +5 -5
  44. package/dist/interfaces/PseudoDocumentFragment.d.ts +7 -0
  45. package/dist/interfaces/PseudoDocumentFragment.js +5 -5
  46. package/dist/interfaces/PseudoElement.d.ts +702 -689
  47. package/dist/interfaces/PseudoElement.js +5 -5
  48. package/dist/interfaces/PseudoEvent.d.ts +79 -79
  49. package/dist/interfaces/PseudoEvent.js +10 -10
  50. package/dist/interfaces/PseudoEventTarget.d.ts +46 -46
  51. package/dist/interfaces/PseudoEventTarget.js +5 -5
  52. package/dist/interfaces/PseudoHTMLCollection.d.ts +23 -23
  53. package/dist/interfaces/PseudoHTMLCollection.js +5 -5
  54. package/dist/interfaces/PseudoHTMLElement.d.ts +22 -22
  55. package/dist/interfaces/PseudoHTMLElement.js +5 -5
  56. package/dist/interfaces/PseudoHTMLSlotElement.d.ts +3 -3
  57. package/dist/interfaces/PseudoHTMLSlotElement.js +5 -5
  58. package/dist/interfaces/PseudoNamedNodeMap.d.ts +11 -11
  59. package/dist/interfaces/PseudoNamedNodeMap.js +5 -5
  60. package/dist/interfaces/PseudoNode.d.ts +179 -179
  61. package/dist/interfaces/PseudoNode.js +5 -5
  62. package/dist/interfaces/PseudoShadowRoot.d.ts +3 -3
  63. package/dist/interfaces/PseudoShadowRoot.js +5 -5
  64. package/dist/main.d.ts +63 -63
  65. package/dist/main.js +155 -155
  66. package/dist/services/AnimationService.d.ts +4 -4
  67. package/dist/services/AnimationService.js +16 -16
  68. package/dist/services/AttrService.d.ts +37 -37
  69. package/dist/services/AttrService.js +81 -81
  70. package/dist/services/CommentService.d.ts +1 -1
  71. package/dist/services/CommentService.js +13 -13
  72. package/dist/services/CustomEventService.d.ts +37 -37
  73. package/dist/services/CustomEventService.js +35 -35
  74. package/dist/services/DOMTokenListService.d.ts +33 -33
  75. package/dist/services/DOMTokenListService.js +117 -117
  76. package/dist/services/DocumentFragmentService.d.ts +8 -0
  77. package/dist/services/DocumentFragmentService.js +18 -0
  78. package/dist/services/DocumentFragmentService.min.js +1 -1
  79. package/dist/services/DocumentService.d.ts +35 -1
  80. package/dist/services/DocumentService.js +72 -0
  81. package/dist/services/DocumentService.min.js +1 -1
  82. package/dist/services/ElementService.d.ts +191 -178
  83. package/dist/services/ElementService.js +426 -406
  84. package/dist/services/ElementService.min.js +1 -1
  85. package/dist/services/EventService.d.ts +120 -120
  86. package/dist/services/EventService.js +250 -250
  87. package/dist/services/EventTargetService.d.ts +84 -84
  88. package/dist/services/EventTargetService.js +232 -232
  89. package/dist/services/FocusEventService.d.ts +32 -32
  90. package/dist/services/FocusEventService.js +35 -35
  91. package/dist/services/HTMLCollectionService.d.ts +54 -49
  92. package/dist/services/HTMLCollectionService.js +92 -75
  93. package/dist/services/HTMLCollectionService.min.js +1 -1
  94. package/dist/services/HTMLElementService.d.ts +57 -57
  95. package/dist/services/HTMLElementService.js +163 -163
  96. package/dist/services/HTMLSlotElementService.d.ts +4 -4
  97. package/dist/services/HTMLSlotElementService.js +9 -9
  98. package/dist/services/InputEventService.d.ts +41 -41
  99. package/dist/services/InputEventService.js +47 -47
  100. package/dist/services/KeyboardEventService.d.ts +70 -70
  101. package/dist/services/KeyboardEventService.js +86 -86
  102. package/dist/services/MouseEventService.d.ts +80 -80
  103. package/dist/services/MouseEventService.js +108 -108
  104. package/dist/services/NamedNodeMapService.d.ts +23 -23
  105. package/dist/services/NamedNodeMapService.js +77 -77
  106. package/dist/services/NodeService.d.ts +297 -271
  107. package/dist/services/NodeService.js +721 -679
  108. package/dist/services/NodeService.min.js +1 -1
  109. package/dist/services/PointerEventService.d.ts +51 -51
  110. package/dist/services/PointerEventService.js +67 -67
  111. package/dist/services/ShadowRootService.d.ts +4 -4
  112. package/dist/services/ShadowRootService.js +9 -9
  113. package/dist/services/TextService.d.ts +1 -1
  114. package/dist/services/TextService.js +13 -13
  115. package/dist/services/UIEventService.d.ts +43 -43
  116. package/dist/services/UIEventService.js +42 -42
  117. package/dist/simulate.d.ts +32 -32
  118. package/dist/simulate.js +115 -115
  119. package/package.json +4 -3
  120. package/dist/classes.d.ts +0 -20
  121. package/dist/classes.js +0 -31
  122. package/dist/classes.min.js +0 -1
  123. package/dist/factories/generateNode.d.ts +0 -32
  124. package/dist/factories/generateNode.js +0 -85
  125. package/dist/factories/generateNode.min.js +0 -1
  126. package/dist/factories.d.ts +0 -11
  127. package/dist/factories.js +0 -27
  128. package/dist/factories.min.js +0 -1
  129. package/dist/functions.d.ts +0 -5
  130. package/dist/functions.js +0 -23
  131. 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