pseudo-dom 0.2.0 → 0.4.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 (62) hide show
  1. package/README.md +903 -43
  2. package/browser/pseudo-dom.js +1489 -376
  3. package/browser/pseudo-dom.min.js +1 -1
  4. package/dist/classes/PseudoEventListener.d.ts +25 -25
  5. package/dist/classes/PseudoEventListener.js +37 -34
  6. package/dist/classes/PseudoEventListener.min.js +1 -1
  7. package/dist/factories/createEvent.d.ts +28 -0
  8. package/dist/factories/createEvent.js +56 -0
  9. package/dist/factories/createEvent.min.js +1 -0
  10. package/dist/factories/eventDefaults.d.ts +31 -0
  11. package/dist/factories/eventDefaults.js +105 -0
  12. package/dist/factories/eventDefaults.min.js +1 -0
  13. package/dist/factories.d.ts +6 -0
  14. package/dist/factories.js +5 -1
  15. package/dist/factories.min.js +1 -1
  16. package/dist/functions/activeElement.d.ts +14 -0
  17. package/dist/functions/activeElement.js +33 -0
  18. package/dist/functions/activeElement.min.js +1 -0
  19. package/dist/functions/modifierState.d.ts +29 -0
  20. package/dist/functions/modifierState.js +41 -0
  21. package/dist/functions/modifierState.min.js +1 -0
  22. package/dist/interfaces/PseudoEventTarget.d.ts +2 -2
  23. package/dist/main.d.ts +32 -1
  24. package/dist/main.js +66 -1
  25. package/dist/main.min.js +1 -1
  26. package/dist/services/CustomEventService.d.ts +37 -0
  27. package/dist/services/CustomEventService.js +35 -0
  28. package/dist/services/CustomEventService.min.js +1 -0
  29. package/dist/services/ElementService.d.ts +1 -0
  30. package/dist/services/ElementService.js +17 -10
  31. package/dist/services/ElementService.min.js +1 -1
  32. package/dist/services/EventService.d.ts +18 -4
  33. package/dist/services/EventService.js +65 -31
  34. package/dist/services/EventService.min.js +1 -1
  35. package/dist/services/EventTargetService.d.ts +41 -9
  36. package/dist/services/EventTargetService.js +121 -52
  37. package/dist/services/EventTargetService.min.js +1 -1
  38. package/dist/services/FocusEventService.d.ts +32 -0
  39. package/dist/services/FocusEventService.js +35 -0
  40. package/dist/services/FocusEventService.min.js +1 -0
  41. package/dist/services/HTMLElementService.d.ts +20 -0
  42. package/dist/services/HTMLElementService.js +95 -0
  43. package/dist/services/HTMLElementService.min.js +1 -1
  44. package/dist/services/InputEventService.d.ts +41 -0
  45. package/dist/services/InputEventService.js +47 -0
  46. package/dist/services/InputEventService.min.js +1 -0
  47. package/dist/services/KeyboardEventService.d.ts +70 -0
  48. package/dist/services/KeyboardEventService.js +86 -0
  49. package/dist/services/KeyboardEventService.min.js +1 -0
  50. package/dist/services/MouseEventService.d.ts +80 -0
  51. package/dist/services/MouseEventService.js +108 -0
  52. package/dist/services/MouseEventService.min.js +1 -0
  53. package/dist/services/PointerEventService.d.ts +51 -0
  54. package/dist/services/PointerEventService.js +67 -0
  55. package/dist/services/PointerEventService.min.js +1 -0
  56. package/dist/services/UIEventService.d.ts +43 -0
  57. package/dist/services/UIEventService.js +42 -0
  58. package/dist/services/UIEventService.min.js +1 -0
  59. package/dist/simulate.d.ts +32 -0
  60. package/dist/simulate.js +115 -0
  61. package/dist/simulate.min.js +1 -0
  62. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -15,7 +15,7 @@ const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
15
15
  Object.defineProperty(exports, '__esModule', {
16
16
  value: true
17
17
  })
18
- exports.PseudoHTMLDocument = exports.PseudoHTMLElement = exports.PseudoElement = exports.PseudoNode = exports.PseudoEventTarget = exports.PseudoEvent = exports.generateDocument = void 0
18
+ exports.PseudoHTMLDocument = exports.PseudoHTMLElement = exports.PseudoElement = exports.PseudoNode = exports.PseudoEventTarget = exports.PseudoCustomEvent = exports.PseudoInputEvent = exports.PseudoFocusEvent = exports.PseudoKeyboardEvent = exports.PseudoPointerEvent = exports.PseudoMouseEvent = exports.PseudoUIEvent = exports.PseudoEvent = exports.simulate = exports.eventDefaults = exports.createEvent = exports.generateDocument = void 0
19
19
  const EventService_1 = require('./services/EventService')
20
20
  Object.defineProperty(exports, 'PseudoEvent', {
21
21
  enumerable: true,
@@ -50,6 +50,61 @@ const PseudoHTMLDocument_1 = __importDefault(require('./classes/PseudoHTMLDocume
50
50
  exports.PseudoHTMLDocument = PseudoHTMLDocument_1.default
51
51
  const generateDocument_1 = __importDefault(require('./factories/generateDocument'))
52
52
  exports.generateDocument = generateDocument_1.default
53
+ const createEvent_1 = __importDefault(require('./factories/createEvent'))
54
+ exports.createEvent = createEvent_1.default
55
+ const eventDefaults_1 = __importDefault(require('./factories/eventDefaults'))
56
+ exports.eventDefaults = eventDefaults_1.default
57
+ const UIEventService_1 = require('./services/UIEventService')
58
+ Object.defineProperty(exports, 'PseudoUIEvent', {
59
+ enumerable: true,
60
+ get: function () {
61
+ return UIEventService_1.UIEventService
62
+ }
63
+ })
64
+ const MouseEventService_1 = require('./services/MouseEventService')
65
+ Object.defineProperty(exports, 'PseudoMouseEvent', {
66
+ enumerable: true,
67
+ get: function () {
68
+ return MouseEventService_1.MouseEventService
69
+ }
70
+ })
71
+ const PointerEventService_1 = require('./services/PointerEventService')
72
+ Object.defineProperty(exports, 'PseudoPointerEvent', {
73
+ enumerable: true,
74
+ get: function () {
75
+ return PointerEventService_1.PointerEventService
76
+ }
77
+ })
78
+ const KeyboardEventService_1 = require('./services/KeyboardEventService')
79
+ Object.defineProperty(exports, 'PseudoKeyboardEvent', {
80
+ enumerable: true,
81
+ get: function () {
82
+ return KeyboardEventService_1.KeyboardEventService
83
+ }
84
+ })
85
+ const FocusEventService_1 = require('./services/FocusEventService')
86
+ Object.defineProperty(exports, 'PseudoFocusEvent', {
87
+ enumerable: true,
88
+ get: function () {
89
+ return FocusEventService_1.FocusEventService
90
+ }
91
+ })
92
+ const InputEventService_1 = require('./services/InputEventService')
93
+ Object.defineProperty(exports, 'PseudoInputEvent', {
94
+ enumerable: true,
95
+ get: function () {
96
+ return InputEventService_1.InputEventService
97
+ }
98
+ })
99
+ const CustomEventService_1 = require('./services/CustomEventService')
100
+ Object.defineProperty(exports, 'PseudoCustomEvent', {
101
+ enumerable: true,
102
+ get: function () {
103
+ return CustomEventService_1.CustomEventService
104
+ }
105
+ })
106
+ const simulate_1 = __importDefault(require('./simulate'))
107
+ exports.simulate = simulate_1.default
53
108
  /**
54
109
  * All methods exported from this module are encapsulated within pseudoDom.
55
110
  * @author Joshua Heagle <joshuaheagle@gmail.com>
@@ -58,7 +113,17 @@ exports.generateDocument = generateDocument_1.default
58
113
  */
59
114
  const pseudoDom = {
60
115
  generateDocument: generateDocument_1.default,
116
+ createEvent: createEvent_1.default,
117
+ eventDefaults: eventDefaults_1.default,
118
+ simulate: simulate_1.default,
61
119
  PseudoEvent: EventService_1.EventService,
120
+ PseudoUIEvent: UIEventService_1.UIEventService,
121
+ PseudoMouseEvent: MouseEventService_1.MouseEventService,
122
+ PseudoPointerEvent: PointerEventService_1.PointerEventService,
123
+ PseudoKeyboardEvent: KeyboardEventService_1.KeyboardEventService,
124
+ PseudoFocusEvent: FocusEventService_1.FocusEventService,
125
+ PseudoInputEvent: InputEventService_1.InputEventService,
126
+ PseudoCustomEvent: CustomEventService_1.CustomEventService,
62
127
  PseudoEventTarget: EventTargetService_1.default,
63
128
  PseudoNode: NodeService_1.NodeService,
64
129
  PseudoElement: ElementService_1.ElementService,
package/dist/main.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.PseudoHTMLDocument=exports.PseudoHTMLElement=exports.PseudoElement=exports.PseudoNode=exports.PseudoEventTarget=exports.PseudoEvent=exports.generateDocument=void 0;const EventService_1=require("./services/EventService");Object.defineProperty(exports,"PseudoEvent",{enumerable:!0,get:function(){return EventService_1.EventService}});const EventTargetService_1=__importDefault(require("./services/EventTargetService"));exports.PseudoEventTarget=EventTargetService_1.default;const NodeService_1=require("./services/NodeService");Object.defineProperty(exports,"PseudoNode",{enumerable:!0,get:function(){return NodeService_1.NodeService}});const ElementService_1=require("./services/ElementService");Object.defineProperty(exports,"PseudoElement",{enumerable:!0,get:function(){return ElementService_1.ElementService}});const HTMLElementService_1=require("./services/HTMLElementService");Object.defineProperty(exports,"PseudoHTMLElement",{enumerable:!0,get:function(){return HTMLElementService_1.HTMLElementService}});const PseudoHTMLDocument_1=__importDefault(require("./classes/PseudoHTMLDocument"));exports.PseudoHTMLDocument=PseudoHTMLDocument_1.default;const generateDocument_1=__importDefault(require("./factories/generateDocument"));exports.generateDocument=generateDocument_1.default;const pseudoDom={generateDocument:generateDocument_1.default,PseudoEvent:EventService_1.EventService,PseudoEventTarget:EventTargetService_1.default,PseudoNode:NodeService_1.NodeService,PseudoElement:ElementService_1.ElementService,PseudoHTMLElement:HTMLElementService_1.HTMLElementService,PseudoHTMLDocument:PseudoHTMLDocument_1.default};exports.default=pseudoDom,"undefined"!=typeof window&&(window.pseudoDom=pseudoDom);
1
+ "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.PseudoHTMLDocument=exports.PseudoHTMLElement=exports.PseudoElement=exports.PseudoNode=exports.PseudoEventTarget=exports.PseudoCustomEvent=exports.PseudoInputEvent=exports.PseudoFocusEvent=exports.PseudoKeyboardEvent=exports.PseudoPointerEvent=exports.PseudoMouseEvent=exports.PseudoUIEvent=exports.PseudoEvent=exports.simulate=exports.eventDefaults=exports.createEvent=exports.generateDocument=void 0;const EventService_1=require("./services/EventService");Object.defineProperty(exports,"PseudoEvent",{enumerable:!0,get:function(){return EventService_1.EventService}});const EventTargetService_1=__importDefault(require("./services/EventTargetService"));exports.PseudoEventTarget=EventTargetService_1.default;const NodeService_1=require("./services/NodeService");Object.defineProperty(exports,"PseudoNode",{enumerable:!0,get:function(){return NodeService_1.NodeService}});const ElementService_1=require("./services/ElementService");Object.defineProperty(exports,"PseudoElement",{enumerable:!0,get:function(){return ElementService_1.ElementService}});const HTMLElementService_1=require("./services/HTMLElementService");Object.defineProperty(exports,"PseudoHTMLElement",{enumerable:!0,get:function(){return HTMLElementService_1.HTMLElementService}});const PseudoHTMLDocument_1=__importDefault(require("./classes/PseudoHTMLDocument"));exports.PseudoHTMLDocument=PseudoHTMLDocument_1.default;const generateDocument_1=__importDefault(require("./factories/generateDocument"));exports.generateDocument=generateDocument_1.default;const createEvent_1=__importDefault(require("./factories/createEvent"));exports.createEvent=createEvent_1.default;const eventDefaults_1=__importDefault(require("./factories/eventDefaults"));exports.eventDefaults=eventDefaults_1.default;const UIEventService_1=require("./services/UIEventService");Object.defineProperty(exports,"PseudoUIEvent",{enumerable:!0,get:function(){return UIEventService_1.UIEventService}});const MouseEventService_1=require("./services/MouseEventService");Object.defineProperty(exports,"PseudoMouseEvent",{enumerable:!0,get:function(){return MouseEventService_1.MouseEventService}});const PointerEventService_1=require("./services/PointerEventService");Object.defineProperty(exports,"PseudoPointerEvent",{enumerable:!0,get:function(){return PointerEventService_1.PointerEventService}});const KeyboardEventService_1=require("./services/KeyboardEventService");Object.defineProperty(exports,"PseudoKeyboardEvent",{enumerable:!0,get:function(){return KeyboardEventService_1.KeyboardEventService}});const FocusEventService_1=require("./services/FocusEventService");Object.defineProperty(exports,"PseudoFocusEvent",{enumerable:!0,get:function(){return FocusEventService_1.FocusEventService}});const InputEventService_1=require("./services/InputEventService");Object.defineProperty(exports,"PseudoInputEvent",{enumerable:!0,get:function(){return InputEventService_1.InputEventService}});const CustomEventService_1=require("./services/CustomEventService");Object.defineProperty(exports,"PseudoCustomEvent",{enumerable:!0,get:function(){return CustomEventService_1.CustomEventService}});const simulate_1=__importDefault(require("./simulate"));exports.simulate=simulate_1.default;const pseudoDom={generateDocument:generateDocument_1.default,createEvent:createEvent_1.default,eventDefaults:eventDefaults_1.default,simulate:simulate_1.default,PseudoEvent:EventService_1.EventService,PseudoUIEvent:UIEventService_1.UIEventService,PseudoMouseEvent:MouseEventService_1.MouseEventService,PseudoPointerEvent:PointerEventService_1.PointerEventService,PseudoKeyboardEvent:KeyboardEventService_1.KeyboardEventService,PseudoFocusEvent:FocusEventService_1.FocusEventService,PseudoInputEvent:InputEventService_1.InputEventService,PseudoCustomEvent:CustomEventService_1.CustomEventService,PseudoEventTarget:EventTargetService_1.default,PseudoNode:NodeService_1.NodeService,PseudoElement:ElementService_1.ElementService,PseudoHTMLElement:HTMLElementService_1.HTMLElementService,PseudoHTMLDocument:PseudoHTMLDocument_1.default};exports.default=pseudoDom,"undefined"!=typeof window&&(window.pseudoDom=pseudoDom);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @file Substitute for the DOM CustomEvent Class.
3
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
4
+ * @version 1.0.0
5
+ */
6
+ import { EventService } from './EventService';
7
+ /**
8
+ * The options for creating a custom event.
9
+ * @typedef {Object} CustomEventInit
10
+ * @property {boolean} [bubbles=false]
11
+ * @property {boolean} [cancelable=false]
12
+ * @property {boolean} [composed=false]
13
+ * @property {*} [detail=null] Whatever data the event should carry
14
+ */
15
+ export type CustomEventInit = {
16
+ bubbles?: boolean;
17
+ cancelable?: boolean;
18
+ composed?: boolean;
19
+ detail?: any;
20
+ };
21
+ /**
22
+ * Simulate the behaviour of the CustomEvent Class when there is no DOM available: an event which carries data.
23
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
24
+ * @class
25
+ * @augments EventService
26
+ * @property {*} detail
27
+ */
28
+ export declare class CustomEventService extends EventService {
29
+ private readonly eventDetail;
30
+ /**
31
+ * @param {string} [typeArg=''] The type of the event
32
+ * @param {CustomEventInit} [init={}] The options for the event
33
+ * @constructor
34
+ */
35
+ constructor(typeArg?: string, init?: CustomEventInit);
36
+ get detail(): any;
37
+ }
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ })
6
+ exports.CustomEventService = void 0
7
+ /**
8
+ * @file Substitute for the DOM CustomEvent Class.
9
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
10
+ * @version 1.0.0
11
+ */
12
+ const EventService_1 = require('./EventService')
13
+ /**
14
+ * Simulate the behaviour of the CustomEvent Class when there is no DOM available: an event which carries data.
15
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
16
+ * @class
17
+ * @augments EventService
18
+ * @property {*} detail
19
+ */
20
+ class CustomEventService extends EventService_1.EventService {
21
+ /**
22
+ * @param {string} [typeArg=''] The type of the event
23
+ * @param {CustomEventInit} [init={}] The options for the event
24
+ * @constructor
25
+ */
26
+ constructor (typeArg = '', init = {}) {
27
+ super(typeArg, init)
28
+ this.eventDetail = typeof init.detail === 'undefined' ? null : init.detail
29
+ }
30
+
31
+ get detail () {
32
+ return this.eventDetail
33
+ }
34
+ }
35
+ exports.CustomEventService = CustomEventService
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CustomEventService=void 0;const EventService_1=require("./EventService");class CustomEventService extends EventService_1.EventService{constructor(e="",t={}){super(e,t),this.eventDetail=void 0===t.detail?null:t.detail}get detail(){return this.eventDetail}}exports.CustomEventService=CustomEventService;
@@ -35,6 +35,7 @@ export declare class ElementService extends NodeService implements Partial<Pseud
35
35
  private readonly attributeList;
36
36
  private readonly propertyAttributes;
37
37
  private readonly tokenList;
38
+ private defaultEventApplied;
38
39
  /**
39
40
  * @param {Object} [settings={}]
40
41
  * @param {string} [settings.tagName=''] The name of the tag this element represents
@@ -16,6 +16,7 @@ Object.defineProperty(exports, '__esModule', {
16
16
  value: true
17
17
  })
18
18
  exports.ElementService = void 0
19
+ const createEvent_1 = __importDefault(require('../factories/createEvent'))
19
20
  const NodeService_1 = require('./NodeService')
20
21
  const AttrService_1 = require('./AttrService')
21
22
  const DOMTokenListService_1 = require('./DOMTokenListService')
@@ -52,6 +53,7 @@ class ElementService extends NodeService_1.NodeService {
52
53
  children = []
53
54
  } = {}) {
54
55
  super()
56
+ this.defaultEventApplied = false
55
57
  this.tokenList = new DOMTokenListService_1.DOMTokenListService()
56
58
  this.tag = tagName
57
59
  this.attributeList = attributes.concat([{
@@ -117,21 +119,26 @@ class ElementService extends NodeService_1.NodeService {
117
119
  */
118
120
  applyDefaultEvent () {
119
121
  let callback = event => undefined
122
+ if (this.defaultEventApplied) {
123
+ return callback
124
+ }
120
125
  switch (this.tagName) {
121
- case 'form':
122
- this.addEventListener('submit', callback)
123
- break
124
126
  case 'button':
125
127
  case 'input':
126
- if (/^(submit|image)$/i.test(this.type || '')) {
127
- callback = event => {
128
- const forms = (0, getParentNodesFromAttribute_1.default)('tagName', 'form', this)
129
- if (forms.length) {
130
- forms[0].submit()
131
- }
128
+ // Clicking a submit button submits the form it is in: the form gets a submit event, which can be cancelled
129
+ callback = event => {
130
+ const type = String(this.getAttribute('type') || this.type || '').toLowerCase()
131
+ const submits = this.tagName === 'button' ? type !== 'button' && type !== 'reset' : /^(submit|image)$/.test(type)
132
+ const forms = (0, getParentNodesFromAttribute_1.default)('tagName', 'form', this)
133
+ if (submits && forms.length && !this.hasAttribute('disabled')) {
134
+ forms[forms.length - 1].dispatchEvent((0, createEvent_1.default)('submit', {}, {
135
+ browser: true,
136
+ trusted: event.isTrusted
137
+ }))
132
138
  }
133
- super.setDefaultEvent('click', callback)
134
139
  }
140
+ super.setDefaultEvent('click', callback)
141
+ this.defaultEventApplied = true
135
142
  }
136
143
  return callback
137
144
  }
@@ -1 +1 @@
1
- "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.for-each.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.iterator.some.js");var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.ElementService=void 0;const NodeService_1=require("./NodeService"),AttrService_1=require("./AttrService"),DOMTokenListService_1=require("./DOMTokenListService"),NamedNodeMapService_1=require("./NamedNodeMapService"),getParentNodesFromAttribute_1=__importDefault(require("../functions/getParentNodesFromAttribute"));class ElementService extends NodeService_1.NodeService{constructor({tagName:e="",attributes:t=[],parent:r=null,children:i=[]}={}){super(),this.tokenList=new DOMTokenListService_1.DOMTokenListService,this.tag=e,this.attributeList=t.concat([{name:"className",value:""},{name:"id",value:""},{name:"innerHTML",value:""}]),this.propertyAttributes=this.attributeList.map(({name:e})=>e),this.attributeList.forEach(({name:e,value:t})=>{this[e]=t}),i.forEach(e=>{if(!e||"number"!=typeof e.nodeType)throw new TypeError("The children of an element must be nodes.");this.appendChild(e)}),r&&r.appendChild(this)}get tagName(){return this.tag}get nodeType(){return NodeService_1.NodeService.ELEMENT_NODE}get attributes(){return new NamedNodeMapService_1.NamedNodeMapService(this.attributeList.map(({name:e,value:t})=>new AttrService_1.AttrService(e,String(t),this)))}get classList(){return this.tokenList}get className(){return this.tokenList.value}set className(e){this.tokenList.value=e}applyDefaultEvent(){let e=e=>{};switch(this.tagName){case"form":this.addEventListener("submit",e);break;case"button":case"input":/^(submit|image)$/i.test(this.type||"")&&(e=e=>{const t=(0,getParentNodesFromAttribute_1.default)("tagName","form",this);t.length&&t[0].submit()},super.setDefaultEvent("click",e))}return e}childInserted(e){"function"==typeof e.applyDefaultEvent&&e.applyDefaultEvent()}hasAttribute(e){return this.attributeList.some(({name:t})=>t===e)}setAttribute(e,t){const r=this.attributeList.find(({name:t})=>t===e);r?r.value=t:this.attributeList.push({name:e,value:t}),this.propertyAttributes.indexOf(e)>=0&&(this[e]=t)}getAttribute(e){const t=this.attributeList.find(({name:t})=>t===e);return t?t.value:null}removeAttribute(e){const t=this.attributeList.findIndex(({name:t})=>t===e);t>=0&&this.attributeList.splice(t,1)}}exports.ElementService=ElementService;
1
+ "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.for-each.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.iterator.some.js");var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.ElementService=void 0;const createEvent_1=__importDefault(require("../factories/createEvent")),NodeService_1=require("./NodeService"),AttrService_1=require("./AttrService"),DOMTokenListService_1=require("./DOMTokenListService"),NamedNodeMapService_1=require("./NamedNodeMapService"),getParentNodesFromAttribute_1=__importDefault(require("../functions/getParentNodesFromAttribute"));class ElementService extends NodeService_1.NodeService{constructor({tagName:e="",attributes:t=[],parent:r=null,children:i=[]}={}){super(),this.defaultEventApplied=!1,this.tokenList=new DOMTokenListService_1.DOMTokenListService,this.tag=e,this.attributeList=t.concat([{name:"className",value:""},{name:"id",value:""},{name:"innerHTML",value:""}]),this.propertyAttributes=this.attributeList.map(({name:e})=>e),this.attributeList.forEach(({name:e,value:t})=>{this[e]=t}),i.forEach(e=>{if(!e||"number"!=typeof e.nodeType)throw new TypeError("The children of an element must be nodes.");this.appendChild(e)}),r&&r.appendChild(this)}get tagName(){return this.tag}get nodeType(){return NodeService_1.NodeService.ELEMENT_NODE}get attributes(){return new NamedNodeMapService_1.NamedNodeMapService(this.attributeList.map(({name:e,value:t})=>new AttrService_1.AttrService(e,String(t),this)))}get classList(){return this.tokenList}get className(){return this.tokenList.value}set className(e){this.tokenList.value=e}applyDefaultEvent(){let e=e=>{};if(this.defaultEventApplied)return e;switch(this.tagName){case"button":case"input":e=e=>{const t=String(this.getAttribute("type")||this.type||"").toLowerCase(),r="button"===this.tagName?"button"!==t&&"reset"!==t:/^(submit|image)$/.test(t),i=(0,getParentNodesFromAttribute_1.default)("tagName","form",this);r&&i.length&&!this.hasAttribute("disabled")&&i[i.length-1].dispatchEvent((0,createEvent_1.default)("submit",{},{browser:!0,trusted:e.isTrusted}))},super.setDefaultEvent("click",e),this.defaultEventApplied=!0}return e}childInserted(e){"function"==typeof e.applyDefaultEvent&&e.applyDefaultEvent()}hasAttribute(e){return this.attributeList.some(({name:t})=>t===e)}setAttribute(e,t){const r=this.attributeList.find(({name:t})=>t===e);r?r.value=t:this.attributeList.push({name:e,value:t}),this.propertyAttributes.indexOf(e)>=0&&(this[e]=t)}getAttribute(e){const t=this.attributeList.find(({name:t})=>t===e);return t?t.value:null}removeAttribute(e){const t=this.attributeList.findIndex(({name:t})=>t===e);t>=0&&this.attributeList.splice(t,1)}}exports.ElementService=ElementService;
@@ -5,12 +5,26 @@
5
5
  */
6
6
  import { PseudoEventTarget } from '../interfaces/PseudoEventTarget';
7
7
  import { PseudoEvent } from '../interfaces/PseudoEvent';
8
+ /**
9
+ * The parts of an event which the dispatching of it (EventTargetService) needs to change or read. Not part of the DOM's
10
+ * Event, which is why they are kept apart from the event's own properties.
11
+ */
8
12
  export type EventInner = {
9
- currentTarget: PseudoEventTarget;
13
+ currentTarget: PseudoEventTarget | null;
10
14
  eventPhase: number;
11
15
  target: PseudoEventTarget;
12
16
  immediatePropagationStopped: boolean;
13
17
  propagationStopped: boolean;
18
+ /** True for an event which the browser created for a user action, an event which a script created is not trusted. */
19
+ trusted: boolean;
20
+ /** True while the event is being dispatched. */
21
+ dispatching: boolean;
22
+ /** True while a passive listener is running, in which preventDefault does nothing. */
23
+ inPassiveListener: boolean;
24
+ /** The targets the event travels through, the target first and the root last, set while dispatching. */
25
+ path: Array<PseudoEventTarget>;
26
+ /** Finish the dispatch: no phase, no current target, no path and the stop flags are cleared so the event can be dispatched again. */
27
+ finishDispatch: () => void;
14
28
  };
15
29
  /**
16
30
  * Simulate the behaviour of the Event Class when there is no DOM available.
@@ -51,9 +65,9 @@ export declare class EventService implements PseudoEvent {
51
65
  *
52
66
  * @param {string} typeArg
53
67
  * @param {Object} [eventOptions={}]
54
- * @param {boolean} [eventOptions.bubbles=true]
55
- * @param {boolean} [eventOptions.cancelable=true]
56
- * @param {boolean} [eventOptions.composed=true]
68
+ * @param {boolean} [eventOptions.bubbles=false]
69
+ * @param {boolean} [eventOptions.cancelable=false]
70
+ * @param {boolean} [eventOptions.composed=false]
57
71
  * @constructor
58
72
  */
59
73
  constructor(typeArg?: string, { bubbles, cancelable, composed }?: {
@@ -5,18 +5,10 @@
5
5
  * @author Joshua Heagle <joshuaheagle@gmail.com>
6
6
  * @version 1.0.0
7
7
  */
8
- const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
9
- return mod && mod.__esModule
10
- ? mod
11
- : {
12
- default: mod
13
- }
14
- }
15
8
  Object.defineProperty(exports, '__esModule', {
16
9
  value: true
17
10
  })
18
11
  exports.EventService = void 0
19
- const getParentNodes_1 = __importDefault(require('../functions/getParentNodes'))
20
12
  /**
21
13
  * Simulate the behaviour of the Event Class when there is no DOM available.
22
14
  * @author Joshua Heagle <joshuaheagle@gmail.com>
@@ -51,20 +43,20 @@ class EventService {
51
43
  *
52
44
  * @param {string} typeArg
53
45
  * @param {Object} [eventOptions={}]
54
- * @param {boolean} [eventOptions.bubbles=true]
55
- * @param {boolean} [eventOptions.cancelable=true]
56
- * @param {boolean} [eventOptions.composed=true]
46
+ * @param {boolean} [eventOptions.bubbles=false]
47
+ * @param {boolean} [eventOptions.cancelable=false]
48
+ * @param {boolean} [eventOptions.composed=false]
57
49
  * @constructor
58
50
  */
59
51
  constructor (typeArg = '', {
60
- bubbles = true,
61
- cancelable = true,
62
- composed = true
52
+ bubbles = false,
53
+ cancelable = false,
54
+ composed = false
63
55
  } = {}) {
64
56
  this.properties = {
65
- bubbles: true,
66
- cancelable: true,
67
- composed: true,
57
+ bubbles: false,
58
+ cancelable: false,
59
+ composed: false,
68
60
  currentTarget: null,
69
61
  defaultPrevented: false,
70
62
  immediatePropagationStopped: false,
@@ -73,7 +65,10 @@ class EventService {
73
65
  target: null,
74
66
  timeStamp: Math.floor(Date.now() / 1000),
75
67
  type: '',
76
- isTrusted: true
68
+ isTrusted: false,
69
+ dispatching: false,
70
+ inPassiveListener: false,
71
+ path: []
77
72
  }
78
73
  this.setReadOnlyProperties({
79
74
  type: typeArg,
@@ -130,12 +125,21 @@ class EventService {
130
125
  get inner () {
131
126
  const self = this
132
127
  return {
128
+ get currentTarget () {
129
+ return self.properties.currentTarget
130
+ },
133
131
  set currentTarget (target) {
134
132
  self.properties.currentTarget = target
135
133
  },
134
+ get eventPhase () {
135
+ return self.properties.eventPhase
136
+ },
136
137
  set eventPhase (phase) {
137
138
  self.properties.eventPhase = phase
138
139
  },
140
+ get target () {
141
+ return self.properties.target
142
+ },
139
143
  set target (target) {
140
144
  self.properties.target = target
141
145
  },
@@ -144,6 +148,41 @@ class EventService {
144
148
  },
145
149
  get propagationStopped () {
146
150
  return self.properties.propagationStopped
151
+ },
152
+ get trusted () {
153
+ return self.properties.isTrusted
154
+ },
155
+ set trusted (trusted) {
156
+ self.properties.isTrusted = trusted
157
+ },
158
+ get dispatching () {
159
+ return self.properties.dispatching
160
+ },
161
+ set dispatching (dispatching) {
162
+ self.properties.dispatching = dispatching
163
+ },
164
+ get inPassiveListener () {
165
+ return self.properties.inPassiveListener
166
+ },
167
+ set inPassiveListener (passive) {
168
+ self.properties.inPassiveListener = passive
169
+ },
170
+ get path () {
171
+ return self.properties.path
172
+ },
173
+ set path (path) {
174
+ self.properties.path = path
175
+ },
176
+ finishDispatch () {
177
+ self.setReadOnlyProperties({
178
+ currentTarget: null,
179
+ eventPhase: EventService.NONE,
180
+ path: [],
181
+ dispatching: false,
182
+ inPassiveListener: false,
183
+ propagationStopped: false,
184
+ immediatePropagationStopped: false
185
+ })
147
186
  }
148
187
  }
149
188
  }
@@ -154,16 +193,8 @@ class EventService {
154
193
  * @returns {Array.<PseudoEventTarget>}
155
194
  */
156
195
  composedPath () {
157
- switch (this.eventPhase) {
158
- case EventService.CAPTURING_PHASE:
159
- return (0, getParentNodes_1.default)(this.target)
160
- case EventService.BUBBLING_PHASE:
161
- return (0, getParentNodes_1.default)(this.target).slice().reverse()
162
- case EventService.AT_TARGET:
163
- return [this.target]
164
- default:
165
- return []
166
- }
196
+ // While the event is being dispatched this is every target it travels through, the target first and the root last
197
+ return this.properties.dispatching ? this.properties.path.slice() : []
167
198
  }
168
199
 
169
200
  /**
@@ -172,9 +203,12 @@ class EventService {
172
203
  * @returns {null}
173
204
  */
174
205
  preventDefault () {
175
- this.setReadOnlyProperties({
176
- defaultPrevented: true
177
- })
206
+ // Only an event which can be cancelled can be prevented, and a passive listener cannot prevent the default
207
+ if (this.cancelable && !this.properties.inPassiveListener) {
208
+ this.setReadOnlyProperties({
209
+ defaultPrevented: true
210
+ })
211
+ }
178
212
  return null
179
213
  }
180
214
 
@@ -1 +1 @@
1
- "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.EventService=void 0;const getParentNodes_1=__importDefault(require("../functions/getParentNodes"));class EventService{constructor(e="",{bubbles:t=!0,cancelable:r=!0,composed:s=!0}={}){this.properties={bubbles:!0,cancelable:!0,composed:!0,currentTarget:null,defaultPrevented:!1,immediatePropagationStopped:!1,propagationStopped:!1,eventPhase:0,target:null,timeStamp:Math.floor(Date.now()/1e3),type:"",isTrusted:!0},this.setReadOnlyProperties({type:e,bubbles:t,cancelable:r,composed:s})}get bubbles(){return this.properties.bubbles}get cancelable(){return this.properties.cancelable}get composed(){return this.properties.composed}get currentTarget(){return this.properties.currentTarget}get defaultPrevented(){return this.properties.defaultPrevented}get eventPhase(){return this.properties.eventPhase}get isTrusted(){return this.properties.isTrusted}get target(){return this.properties.target}get timeStamp(){return this.properties.timeStamp}get type(){return this.properties.type}get inner(){const e=this;return{set currentTarget(t){e.properties.currentTarget=t},set eventPhase(t){e.properties.eventPhase=t},set target(t){e.properties.target=t},get immediatePropagationStopped(){return e.properties.immediatePropagationStopped},get propagationStopped(){return e.properties.propagationStopped}}}composedPath(){switch(this.eventPhase){case EventService.CAPTURING_PHASE:return(0,getParentNodes_1.default)(this.target);case EventService.BUBBLING_PHASE:return(0,getParentNodes_1.default)(this.target).slice().reverse();case EventService.AT_TARGET:return[this.target];default:return[]}}preventDefault(){return this.setReadOnlyProperties({defaultPrevented:!0}),null}stopImmediatePropagation(){return this.setReadOnlyProperties({immediatePropagationStopped:!0}),null}stopPropagation(){return this.setReadOnlyProperties({propagationStopped:!0}),null}setReadOnlyProperties(e={}){return this.properties=Object.assign({},this.properties,e),this}}exports.EventService=EventService,EventService.NONE=0,EventService.CAPTURING_PHASE=1,EventService.AT_TARGET=2,EventService.BUBBLING_PHASE=3;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.EventService=void 0;class EventService{constructor(e="",{bubbles:t=!1,cancelable:r=!1,composed:s=!1}={}){this.properties={bubbles:!1,cancelable:!1,composed:!1,currentTarget:null,defaultPrevented:!1,immediatePropagationStopped:!1,propagationStopped:!1,eventPhase:0,target:null,timeStamp:Math.floor(Date.now()/1e3),type:"",isTrusted:!1,dispatching:!1,inPassiveListener:!1,path:[]},this.setReadOnlyProperties({type:e,bubbles:t,cancelable:r,composed:s})}get bubbles(){return this.properties.bubbles}get cancelable(){return this.properties.cancelable}get composed(){return this.properties.composed}get currentTarget(){return this.properties.currentTarget}get defaultPrevented(){return this.properties.defaultPrevented}get eventPhase(){return this.properties.eventPhase}get isTrusted(){return this.properties.isTrusted}get target(){return this.properties.target}get timeStamp(){return this.properties.timeStamp}get type(){return this.properties.type}get inner(){const e=this;return{get currentTarget(){return e.properties.currentTarget},set currentTarget(t){e.properties.currentTarget=t},get eventPhase(){return e.properties.eventPhase},set eventPhase(t){e.properties.eventPhase=t},get target(){return e.properties.target},set target(t){e.properties.target=t},get immediatePropagationStopped(){return e.properties.immediatePropagationStopped},get propagationStopped(){return e.properties.propagationStopped},get trusted(){return e.properties.isTrusted},set trusted(t){e.properties.isTrusted=t},get dispatching(){return e.properties.dispatching},set dispatching(t){e.properties.dispatching=t},get inPassiveListener(){return e.properties.inPassiveListener},set inPassiveListener(t){e.properties.inPassiveListener=t},get path(){return e.properties.path},set path(t){e.properties.path=t},finishDispatch(){e.setReadOnlyProperties({currentTarget:null,eventPhase:EventService.NONE,path:[],dispatching:!1,inPassiveListener:!1,propagationStopped:!1,immediatePropagationStopped:!1})}}}composedPath(){return this.properties.dispatching?this.properties.path.slice():[]}preventDefault(){return this.cancelable&&!this.properties.inPassiveListener&&this.setReadOnlyProperties({defaultPrevented:!0}),null}stopImmediatePropagation(){return this.setReadOnlyProperties({immediatePropagationStopped:!0}),null}stopPropagation(){return this.setReadOnlyProperties({propagationStopped:!0}),null}setReadOnlyProperties(e={}){return this.properties=Object.assign({},this.properties,e),this}}exports.EventService=EventService,EventService.NONE=0,EventService.CAPTURING_PHASE=1,EventService.AT_TARGET=2,EventService.BUBBLING_PHASE=3;
@@ -7,6 +7,9 @@ import { EventService } from './EventService';
7
7
  import { listenerOptions, PseudoEventTarget } from '../interfaces/PseudoEventTarget';
8
8
  /**
9
9
  * Simulate the behaviour of the EventTarget Class when there is no DOM available.
10
+ * Dispatching an event sends it through the tree the way the DOM does: down from the root to the target (capture
11
+ * listeners), to the target itself, then back up to the root (the listeners which are not capture listeners, when the
12
+ * event bubbles).
10
13
  * @author Joshua Heagle <joshuaheagle@gmail.com>
11
14
  * @class
12
15
  * @property {Object.<string, Array.<PseudoEventListener>>} listeners
@@ -28,25 +31,54 @@ declare class EventTargetService implements PseudoEventTarget {
28
31
  */
29
32
  private listenersFor;
30
33
  /**
31
- * Run each of the listeners registered on this target for the type of the event.
32
- * Listeners which do not apply to the event's phase are skipped, running stops once immediate propagation is stopped,
33
- * and listeners added or removed while running do not change which ones run for this event.
34
- * @param {EventService} event
35
- * @returns {*} true when there was nothing registered, otherwise the last value returned from a handler (null when none ran)
34
+ * Run the listeners registered on this target for the type of the event which apply to the phase the event is in
35
+ * (at the target, the capture listeners run before the others). Listeners which are added while this runs do not run
36
+ * for this event, and listeners which are removed while it runs no longer do. Running stops as soon as immediate
37
+ * propagation is stopped. A listener which throws does not stop the others.
38
+ * @param {EventService} event The event, which is at a phase and has a current target
39
+ * @returns {Array<*>} The errors which the listeners threw
36
40
  */
37
41
  private runEvents;
42
+ /**
43
+ * Take a listener out of the registered listeners, so that it does not run again.
44
+ * @param {string} type
45
+ * @param {PseudoEventListener} listener
46
+ */
47
+ private removeListener;
38
48
  /**
39
49
  * Register the function to run when nothing else has prevented the default for this type of event.
40
50
  * @param {string} type
41
51
  * @param {Function} callback
42
52
  */
43
53
  protected setDefaultEvent(type: string, callback: Function): void;
44
- private runDefaultEvent;
45
- private startEvents;
54
+ /**
55
+ * Registers an event handler of a specific event type. Adding the same handler again for the same type and phase does
56
+ * nothing, like the DOM.
57
+ * @param {string} type The type of event to listen for
58
+ * @param {Function|Object} callback The function to call (or an object with a handleEvent function)
59
+ * @param {Object|boolean} [useCapture=false] Listen while the event travels down to the target (true), or an object with capture, once and passive
60
+ */
46
61
  addEventListener(type: string, callback: Function | {
47
62
  handleEvent: Function;
48
63
  } | any, useCapture?: listenerOptions | boolean): void;
49
- removeEventListener(type: string, callback: Function): void;
50
- dispatchEvent(event: EventService, target?: EventTargetService): boolean;
64
+ /**
65
+ * Removes an event listener, the one which was added with the same type, handler and phase.
66
+ * @param {string} type The type of event
67
+ * @param {Function|Object} callback The handler which was added
68
+ * @param {Object|boolean} [options=false] Whether the listener was a capture listener (true), or an object with capture
69
+ */
70
+ removeEventListener(type: string, callback: Function, options?: listenerOptions | boolean): void;
71
+ /**
72
+ * Dispatches an event to this target and through the tree: capture listeners of the ancestors from the root down,
73
+ * then the listeners of this target, then (when the event bubbles) the other listeners of the ancestors from the
74
+ * parent up to the root. stopPropagation() stops it reaching further targets, stopImmediatePropagation() also stops
75
+ * the remaining listeners of the current target. Afterwards, unless the default was prevented, the default action
76
+ * of this target (see setDefaultEvent) runs. The event can be dispatched again afterwards.
77
+ * @param {EventService} event The event to dispatch
78
+ * @returns {boolean} False when the event was cancelable and a listener prevented the default, otherwise true
79
+ * @throws {Error} When the event is already being dispatched, or (after the whole dispatch has finished) the error
80
+ * which a listener threw (an error with all of them in its errors property when several did)
81
+ */
82
+ dispatchEvent(event: EventService): boolean;
51
83
  }
52
84
  export default EventTargetService;