pseudo-dom 0.8.0 → 0.9.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 (30) hide show
  1. package/README.md +206 -1
  2. package/browser/pseudo-dom.js +813 -470
  3. package/browser/pseudo-dom.min.js +1 -1
  4. package/dist/classes/PseudoHTMLDocument.d.ts +41 -41
  5. package/dist/classes/PseudoHTMLDocument.js +74 -74
  6. package/dist/factories/createDataset.d.ts +10 -0
  7. package/dist/factories/createDataset.js +78 -0
  8. package/dist/factories/createDataset.min.js +1 -0
  9. package/dist/factories/createStyleDeclaration.d.ts +30 -0
  10. package/dist/factories/createStyleDeclaration.js +64 -0
  11. package/dist/factories/createStyleDeclaration.min.js +1 -0
  12. package/dist/functions/getElementById.d.ts +13 -13
  13. package/dist/functions/getElementById.js +33 -33
  14. package/dist/interfaces/PseudoCSSStyleDeclaration.d.ts +14 -0
  15. package/dist/interfaces/PseudoCSSStyleDeclaration.js +5 -0
  16. package/dist/interfaces/PseudoCSSStyleDeclaration.min.js +1 -0
  17. package/dist/interfaces/PseudoDocument.d.ts +35 -35
  18. package/dist/interfaces/PseudoDocumentFragment.d.ts +10 -10
  19. package/dist/interfaces/PseudoHTMLElement.d.ts +33 -22
  20. package/dist/services/CSSStyleDeclarationService.d.ts +73 -0
  21. package/dist/services/CSSStyleDeclarationService.js +156 -0
  22. package/dist/services/CSSStyleDeclarationService.min.js +1 -0
  23. package/dist/services/DocumentFragmentService.d.ts +21 -21
  24. package/dist/services/DocumentFragmentService.js +42 -42
  25. package/dist/services/DocumentService.d.ts +46 -46
  26. package/dist/services/DocumentService.js +95 -95
  27. package/dist/services/HTMLElementService.d.ts +87 -57
  28. package/dist/services/HTMLElementService.js +202 -163
  29. package/dist/services/HTMLElementService.min.js +1 -1
  30. package/package.json +1 -1
@@ -1,163 +1,202 @@
1
- 'use strict'
2
-
3
- const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
4
- return mod && mod.__esModule
5
- ? mod
6
- : {
7
- default: mod
8
- }
9
- }
10
- Object.defineProperty(exports, '__esModule', {
11
- value: true
12
- })
13
- exports.HTMLElementService = void 0
14
- const ElementService_1 = require('./ElementService')
15
- const createEvent_1 = __importDefault(require('../factories/createEvent'))
16
- const activeElement_1 = require('../functions/activeElement')
17
- /**
18
- * Simulate the behaviour of the HTMLElement Class when there is no DOM available.
19
- * @author Joshua Heagle <joshuaheagle@gmail.com>
20
- * @class
21
- * @augments PseudoElement
22
- * @property {boolean} hidden - State of whether element is visible
23
- * @property {number} offsetHeight - The height of the element as offset by the parent element
24
- * @property {number} offsetLeft - The position of the left side of the element based on the parent element
25
- * @property {PseudoHTMLElement} offsetParent - A reference to the closest positioned parent element
26
- * @property {number} offsetTop - The position of the top side of the element based on the parent element
27
- * @property {number} offsetWidth - The width of the element as offset by the parent element
28
- * @property {Object} style - A container to define all applied inline-styles
29
- * @property {string} title - The title attribute which affects the text visible on hover
30
- */
31
- class HTMLElementService extends ElementService_1.ElementService {
32
- /**
33
- * Simulate the HTMLElement object when the Dom is not available
34
- * @param {Object} [elementOptions={}]
35
- * @param {string} [elementOptions.tagName='']
36
- * @param {PseudoNode|Object} [elementOptions.parent={}]
37
- * @param {Array} [elementOptions.children=[]]
38
- * @constructor
39
- */
40
- constructor ({
41
- tagName = '',
42
- parent = null,
43
- children = []
44
- } = {}) {
45
- super({
46
- tagName,
47
- attributes: [{
48
- name: 'hidden',
49
- value: false
50
- }, {
51
- name: 'offsetHeight',
52
- value: 0
53
- }, {
54
- name: 'offsetLeft',
55
- value: 0
56
- }, {
57
- name: 'offsetParent',
58
- value: null
59
- }, {
60
- name: 'offsetTop',
61
- value: 0
62
- }, {
63
- name: 'offsetWidth',
64
- value: 0
65
- }, {
66
- name: 'style',
67
- value: {}
68
- }, {
69
- name: 'title',
70
- value: ''
71
- }],
72
- parent,
73
- children
74
- })
75
- }
76
-
77
- /**
78
- * Whether this element can have the focus: form controls and links which are not disabled, and anything with a tabindex.
79
- * @returns {boolean}
80
- */
81
- get canFocus () {
82
- if (this.hasAttribute('disabled')) {
83
- return false
84
- }
85
- switch (this.tagName) {
86
- case 'button':
87
- case 'select':
88
- case 'textarea':
89
- return true
90
- case 'input':
91
- return String(this.getAttribute('type') || '').toLowerCase() !== 'hidden'
92
- case 'a':
93
- return this.hasAttribute('href') || this.hasAttribute('tabindex')
94
- default:
95
- return this.hasAttribute('tabindex')
96
- }
97
- }
98
-
99
- /**
100
- * Click the element: a click event is sent to it, which bubbles and can be cancelled, like one from a user but a
101
- * script made it (so it is not trusted). A disabled element does nothing.
102
- */
103
- click () {
104
- if (this.hasAttribute('disabled')) {
105
- return
106
- }
107
- this.dispatchEvent((0, createEvent_1.default)('click', {}, {
108
- browser: true
109
- }))
110
- }
111
-
112
- /**
113
- * Give the element the focus. The element which had it gets blur then focusout, and this one gets focus then
114
- * focusin (blur and focus do not bubble, focusin and focusout do). Nothing happens when the element cannot have the
115
- * focus or already has it.
116
- */
117
- focus () {
118
- const root = this.getRootNode()
119
- const previous = (0, activeElement_1.getActiveElement)(root)
120
- if (!this.canFocus || previous === this) {
121
- return
122
- }
123
- const send = (target, type, relatedTarget) => {
124
- target.dispatchEvent((0, createEvent_1.default)(type, {
125
- relatedTarget
126
- }, {
127
- browser: true,
128
- trusted: true
129
- }))
130
- }
131
- if (previous) {
132
- send(previous, 'blur', this)
133
- send(previous, 'focusout', this)
134
- }
135
- (0, activeElement_1.setActiveElement)(root, this)
136
- send(this, 'focus', previous)
137
- send(this, 'focusin', previous)
138
- }
139
-
140
- /**
141
- * Take the focus away from the element, when it has it: it gets blur then focusout.
142
- */
143
- blur () {
144
- const root = this.getRootNode()
145
- if ((0, activeElement_1.getActiveElement)(root) !== this) {
146
- return
147
- }
148
- (0, activeElement_1.setActiveElement)(root, null)
149
- this.dispatchEvent((0, createEvent_1.default)('blur', {
150
- relatedTarget: null
151
- }, {
152
- browser: true,
153
- trusted: true
154
- }))
155
- this.dispatchEvent((0, createEvent_1.default)('focusout', {
156
- relatedTarget: null
157
- }, {
158
- browser: true,
159
- trusted: true
160
- }))
161
- }
162
- }
163
- exports.HTMLElementService = HTMLElementService
1
+ 'use strict'
2
+
3
+ const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
4
+ return mod && mod.__esModule
5
+ ? mod
6
+ : {
7
+ default: mod
8
+ }
9
+ }
10
+ Object.defineProperty(exports, '__esModule', {
11
+ value: true
12
+ })
13
+ exports.HTMLElementService = void 0
14
+ const ElementService_1 = require('./ElementService')
15
+ const createEvent_1 = __importDefault(require('../factories/createEvent'))
16
+ const activeElement_1 = require('../functions/activeElement')
17
+ const createStyleDeclaration_1 = __importDefault(require('../factories/createStyleDeclaration'))
18
+ const createDataset_1 = __importDefault(require('../factories/createDataset'))
19
+ /**
20
+ * Simulate the behaviour of the HTMLElement Class when there is no DOM available.
21
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
22
+ * @class
23
+ * @augments PseudoElement
24
+ * @property {boolean} hidden - State of whether element is visible
25
+ * @property {number} offsetHeight - The height of the element as offset by the parent element
26
+ * @property {number} offsetLeft - The position of the left side of the element based on the parent element
27
+ * @property {PseudoHTMLElement} offsetParent - A reference to the closest positioned parent element
28
+ * @property {number} offsetTop - The position of the top side of the element based on the parent element
29
+ * @property {number} offsetWidth - The width of the element as offset by the parent element
30
+ * @property {CSSStyleDeclarationService} style - The element's inline styles, live and settable per property
31
+ * @property {Object.<string, string>} dataset - The element's data-* attributes, live, under their camelCase names
32
+ * @property {string} title - The title attribute which affects the text visible on hover
33
+ */
34
+ class HTMLElementService extends ElementService_1.ElementService {
35
+ /**
36
+ * Simulate the HTMLElement object when the Dom is not available
37
+ * @param {Object} [elementOptions={}]
38
+ * @param {string} [elementOptions.tagName='']
39
+ * @param {PseudoNode|Object} [elementOptions.parent={}]
40
+ * @param {Array} [elementOptions.children=[]]
41
+ * @constructor
42
+ */
43
+ constructor ({
44
+ tagName = '',
45
+ parent = null,
46
+ children = []
47
+ } = {}) {
48
+ super({
49
+ tagName,
50
+ attributes: [{
51
+ name: 'hidden',
52
+ value: false
53
+ }, {
54
+ name: 'offsetHeight',
55
+ value: 0
56
+ }, {
57
+ name: 'offsetLeft',
58
+ value: 0
59
+ }, {
60
+ name: 'offsetParent',
61
+ value: null
62
+ }, {
63
+ name: 'offsetTop',
64
+ value: 0
65
+ }, {
66
+ name: 'offsetWidth',
67
+ value: 0
68
+ }, {
69
+ name: 'title',
70
+ value: ''
71
+ }],
72
+ parent,
73
+ children
74
+ })
75
+ this.styleDeclaration = (0, createStyleDeclaration_1.default)()
76
+ this.datasetProxy = (0, createDataset_1.default)(this)
77
+ }
78
+
79
+ /**
80
+ * The element's inline styles: a live CSSStyleDeclaration-like object, so both style.setProperty('color', 'red')
81
+ * and style.color = 'red' work.
82
+ * @returns {CSSStyleDeclarationService}
83
+ */
84
+ get style () {
85
+ return this.styleDeclaration
86
+ }
87
+
88
+ /**
89
+ * The element's data-* attributes, live, under their camelCase names (data-foo-bar <-> dataset.fooBar). Backed
90
+ * directly by getAttribute / setAttribute, so it is never out of sync with the attributes themselves.
91
+ * @returns {Object.<string, string>}
92
+ */
93
+ get dataset () {
94
+ return this.datasetProxy
95
+ }
96
+
97
+ /**
98
+ * Style is not attribute-backed like most properties (see the constructor), so cloneNode needs its own copy of it.
99
+ * @returns {NodeService}
100
+ */
101
+ cloneShallow () {
102
+ const copy = super.cloneShallow()
103
+ copy.style.cssText = this.style.cssText
104
+ return copy
105
+ }
106
+
107
+ /**
108
+ * Style is not attribute-backed like most properties, so isEqualNode needs to compare it separately too.
109
+ * @param {NodeService} other The node to compare with
110
+ * @returns {boolean}
111
+ */
112
+ equalsShallow (other) {
113
+ return super.equalsShallow(other) && this.style.cssText === other.style.cssText
114
+ }
115
+
116
+ /**
117
+ * Whether this element can have the focus: form controls and links which are not disabled, and anything with a tabindex.
118
+ * @returns {boolean}
119
+ */
120
+ get canFocus () {
121
+ if (this.hasAttribute('disabled')) {
122
+ return false
123
+ }
124
+ switch (this.tagName) {
125
+ case 'button':
126
+ case 'select':
127
+ case 'textarea':
128
+ return true
129
+ case 'input':
130
+ return String(this.getAttribute('type') || '').toLowerCase() !== 'hidden'
131
+ case 'a':
132
+ return this.hasAttribute('href') || this.hasAttribute('tabindex')
133
+ default:
134
+ return this.hasAttribute('tabindex')
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Click the element: a click event is sent to it, which bubbles and can be cancelled, like one from a user but a
140
+ * script made it (so it is not trusted). A disabled element does nothing.
141
+ */
142
+ click () {
143
+ if (this.hasAttribute('disabled')) {
144
+ return
145
+ }
146
+ this.dispatchEvent((0, createEvent_1.default)('click', {}, {
147
+ browser: true
148
+ }))
149
+ }
150
+
151
+ /**
152
+ * Give the element the focus. The element which had it gets blur then focusout, and this one gets focus then
153
+ * focusin (blur and focus do not bubble, focusin and focusout do). Nothing happens when the element cannot have the
154
+ * focus or already has it.
155
+ */
156
+ focus () {
157
+ const root = this.getRootNode()
158
+ const previous = (0, activeElement_1.getActiveElement)(root)
159
+ if (!this.canFocus || previous === this) {
160
+ return
161
+ }
162
+ const send = (target, type, relatedTarget) => {
163
+ target.dispatchEvent((0, createEvent_1.default)(type, {
164
+ relatedTarget
165
+ }, {
166
+ browser: true,
167
+ trusted: true
168
+ }))
169
+ }
170
+ if (previous) {
171
+ send(previous, 'blur', this)
172
+ send(previous, 'focusout', this)
173
+ }
174
+ (0, activeElement_1.setActiveElement)(root, this)
175
+ send(this, 'focus', previous)
176
+ send(this, 'focusin', previous)
177
+ }
178
+
179
+ /**
180
+ * Take the focus away from the element, when it has it: it gets blur then focusout.
181
+ */
182
+ blur () {
183
+ const root = this.getRootNode()
184
+ if ((0, activeElement_1.getActiveElement)(root) !== this) {
185
+ return
186
+ }
187
+ (0, activeElement_1.setActiveElement)(root, null)
188
+ this.dispatchEvent((0, createEvent_1.default)('blur', {
189
+ relatedTarget: null
190
+ }, {
191
+ browser: true,
192
+ trusted: true
193
+ }))
194
+ this.dispatchEvent((0, createEvent_1.default)('focusout', {
195
+ relatedTarget: null
196
+ }, {
197
+ browser: true,
198
+ trusted: true
199
+ }))
200
+ }
201
+ }
202
+ exports.HTMLElementService = HTMLElementService
@@ -1 +1 @@
1
- "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.HTMLElementService=void 0;const ElementService_1=require("./ElementService"),createEvent_1=__importDefault(require("../factories/createEvent")),activeElement_1=require("../functions/activeElement");class HTMLElementService extends ElementService_1.ElementService{constructor({tagName:e="",parent:t=null,children:r=[]}={}){super({tagName:e,attributes:[{name:"hidden",value:!1},{name:"offsetHeight",value:0},{name:"offsetLeft",value:0},{name:"offsetParent",value:null},{name:"offsetTop",value:0},{name:"offsetWidth",value:0},{name:"style",value:{}},{name:"title",value:""}],parent:t,children:r})}get canFocus(){if(this.hasAttribute("disabled"))return!1;switch(this.tagName){case"button":case"select":case"textarea":return!0;case"input":return"hidden"!==String(this.getAttribute("type")||"").toLowerCase();case"a":return this.hasAttribute("href")||this.hasAttribute("tabindex");default:return this.hasAttribute("tabindex")}}click(){this.hasAttribute("disabled")||this.dispatchEvent((0,createEvent_1.default)("click",{},{browser:!0}))}focus(){const e=this.getRootNode(),t=(0,activeElement_1.getActiveElement)(e);if(!this.canFocus||t===this)return;const r=(e,t,r)=>{e.dispatchEvent((0,createEvent_1.default)(t,{relatedTarget:r},{browser:!0,trusted:!0}))};t&&(r(t,"blur",this),r(t,"focusout",this)),(0,activeElement_1.setActiveElement)(e,this),r(this,"focus",t),r(this,"focusin",t)}blur(){const e=this.getRootNode();(0,activeElement_1.getActiveElement)(e)===this&&((0,activeElement_1.setActiveElement)(e,null),this.dispatchEvent((0,createEvent_1.default)("blur",{relatedTarget:null},{browser:!0,trusted:!0})),this.dispatchEvent((0,createEvent_1.default)("focusout",{relatedTarget:null},{browser:!0,trusted:!0})))}}exports.HTMLElementService=HTMLElementService;
1
+ "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.HTMLElementService=void 0;const ElementService_1=require("./ElementService"),createEvent_1=__importDefault(require("../factories/createEvent")),activeElement_1=require("../functions/activeElement"),createStyleDeclaration_1=__importDefault(require("../factories/createStyleDeclaration")),createDataset_1=__importDefault(require("../factories/createDataset"));class HTMLElementService extends ElementService_1.ElementService{constructor({tagName:e="",parent:t=null,children:a=[]}={}){super({tagName:e,attributes:[{name:"hidden",value:!1},{name:"offsetHeight",value:0},{name:"offsetLeft",value:0},{name:"offsetParent",value:null},{name:"offsetTop",value:0},{name:"offsetWidth",value:0},{name:"title",value:""}],parent:t,children:a}),this.styleDeclaration=(0,createStyleDeclaration_1.default)(),this.datasetProxy=(0,createDataset_1.default)(this)}get style(){return this.styleDeclaration}get dataset(){return this.datasetProxy}cloneShallow(){const e=super.cloneShallow();return e.style.cssText=this.style.cssText,e}equalsShallow(e){return super.equalsShallow(e)&&this.style.cssText===e.style.cssText}get canFocus(){if(this.hasAttribute("disabled"))return!1;switch(this.tagName){case"button":case"select":case"textarea":return!0;case"input":return"hidden"!==String(this.getAttribute("type")||"").toLowerCase();case"a":return this.hasAttribute("href")||this.hasAttribute("tabindex");default:return this.hasAttribute("tabindex")}}click(){this.hasAttribute("disabled")||this.dispatchEvent((0,createEvent_1.default)("click",{},{browser:!0}))}focus(){const e=this.getRootNode(),t=(0,activeElement_1.getActiveElement)(e);if(!this.canFocus||t===this)return;const a=(e,t,a)=>{e.dispatchEvent((0,createEvent_1.default)(t,{relatedTarget:a},{browser:!0,trusted:!0}))};t&&(a(t,"blur",this),a(t,"focusout",this)),(0,activeElement_1.setActiveElement)(e,this),a(this,"focus",t),a(this,"focusin",t)}blur(){const e=this.getRootNode();(0,activeElement_1.getActiveElement)(e)===this&&((0,activeElement_1.setActiveElement)(e,null),this.dispatchEvent((0,createEvent_1.default)("blur",{relatedTarget:null},{browser:!0,trusted:!0})),this.dispatchEvent((0,createEvent_1.default)("focusout",{relatedTarget:null},{browser:!0,trusted:!0})))}}exports.HTMLElementService=HTMLElementService;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pseudo-dom",
3
3
  "description": "Mock the DOM on the server side for managing state and testing",
4
- "version": "0.8.0",
4
+ "version": "0.9.0",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
7
7
  "author": "Joshua Heagle",