pseudo-dom 0.5.0 → 0.6.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.
@@ -470,9 +470,10 @@ export interface PseudoElement extends PseudoNode {
470
470
  */
471
471
  set ariaValueText(value: string);
472
472
  /**
473
- * Inserts a set of Node objects or strings in the children list of the Element's parent, just after the Element.
473
+ * Inserts a set of Node objects or strings in the children list of the Element's parent, just after the Element. Does
474
+ * nothing when the element has no parent.
474
475
  */
475
- after(...nodes: PseudoNode[]): void;
476
+ after(...nodes: Array<PseudoNode | string>): void;
476
477
  /**
477
478
  * A shortcut method to create and run an animation on an element. Returns the created Animation object instance.
478
479
  */
@@ -485,7 +486,7 @@ export interface PseudoElement extends PseudoNode {
485
486
  /**
486
487
  * Inserts a set of Node objects or strings after the last child of the element.
487
488
  */
488
- append(...params: PseudoNode[]): void;
489
+ append(...nodes: Array<PseudoNode | string>): void;
489
490
  /**
490
491
  * Attaches a shadow DOM tree to the specified element and returns a reference to its ShadowRoot.
491
492
  */
@@ -496,9 +497,10 @@ export interface PseudoElement extends PseudoNode {
496
497
  slotAssignment: string;
497
498
  }): PseudoShadowRoot;
498
499
  /**
499
- * Inserts a set of Node objects or strings in the children list of the Element's parent, just before the Element.
500
+ * Inserts a set of Node objects or strings in the children list of the Element's parent, just before the Element. Does
501
+ * nothing when the element has no parent.
500
502
  */
501
- before(...params: PseudoNode[]): void;
503
+ before(...nodes: Array<PseudoNode | string>): void;
502
504
  /**
503
505
  * Returns whether an element is expected to be visible or not based on configurable checks.
504
506
  */
@@ -572,17 +574,25 @@ export interface PseudoElement extends PseudoNode {
572
574
  */
573
575
  hasPointerCapture(): string;
574
576
  /**
575
- * Inserts a given element node at a given position relative to the element it is invoked upon.
577
+ * Inserts a given element at a given position relative to the element it is invoked upon.
578
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
579
+ * @param {PseudoElement} element The element to insert
580
+ * @returns {PseudoElement|null} The inserted element, or null when the position needs a parent this element does not have
576
581
  */
577
- insertAdjacentElement(): string;
582
+ insertAdjacentElement(position: string, element: PseudoElement): PseudoElement | null;
578
583
  /**
579
- * Parses the text as HTML or XML and inserts the resulting nodes into the tree in the position given.
584
+ * Parses the text as HTML or XML and inserts the resulting nodes into the tree in the position given. Not implemented
585
+ * yet (HTML parsing is out of scope for now).
586
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
587
+ * @param {string} text The markup to parse
580
588
  */
581
- insertAdjacentHTML(): string;
589
+ insertAdjacentHTML(position: string, text: string): void;
582
590
  /**
583
- * Inserts a given text node at a given position relative to the element it is invoked upon.
591
+ * Inserts a given text at a given position relative to the element it is invoked upon.
592
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
593
+ * @param {string} text The text to insert
584
594
  */
585
- insertAdjacentText(): string;
595
+ insertAdjacentText(position: string, text: string): void;
586
596
  /**
587
597
  * Returns a boolean value indicating whether or not the element would be selected by the specified selector string.
588
598
  */
@@ -590,7 +600,7 @@ export interface PseudoElement extends PseudoNode {
590
600
  /**
591
601
  * Inserts a set of Node objects or strings before the first child of the element.
592
602
  */
593
- prepend(): string;
603
+ prepend(...nodes: Array<PseudoNode | string>): void;
594
604
  /**
595
605
  * Returns the first Node which matches the specified selector string relative to the element.
596
606
  */
@@ -604,9 +614,9 @@ export interface PseudoElement extends PseudoNode {
604
614
  */
605
615
  releasePointerCapture(): string;
606
616
  /**
607
- * Removes the element from the children list of its parent.
617
+ * Removes the element from the children list of its parent. Does nothing when it has no parent.
608
618
  */
609
- remove(): string;
619
+ remove(): void;
610
620
  /**
611
621
  * Removes the named attribute from the current node.
612
622
  */
@@ -622,11 +632,12 @@ export interface PseudoElement extends PseudoNode {
622
632
  /**
623
633
  * Replaces the existing children of a Node with a specified new set of children.
624
634
  */
625
- replaceChildren(): string;
635
+ replaceChildren(...nodes: Array<PseudoNode | string>): void;
626
636
  /**
627
- * Replaces the element in the children list of its parent with a set of Node objects or strings.
637
+ * Replaces the element in the children list of its parent with a set of Node objects or strings. Does nothing when it
638
+ * has no parent.
628
639
  */
629
- replaceWith(): string;
640
+ replaceWith(...nodes: Array<PseudoNode | string>): void;
630
641
  /**
631
642
  * Asynchronously asks the browser to make the element fullscreen.
632
643
  */
@@ -1,2 +1,23 @@
1
- export interface PseudoHTMLCollection {
1
+ import { PseudoElement } from './PseudoElement';
2
+ /**
3
+ * A live collection of an element's (or a document's / document fragment's) element children: it is not a snapshot,
4
+ * reading it after the tree changes reflects the change.
5
+ */
6
+ export interface PseudoHTMLCollection extends Iterable<PseudoElement> {
7
+ /**
8
+ * How many elements are in the collection.
9
+ */
10
+ get length(): number;
11
+ /**
12
+ * The element at the given index, or null when there is none.
13
+ * @param {number} index
14
+ * @returns {PseudoElement|null}
15
+ */
16
+ item(index: number): PseudoElement | null;
17
+ /**
18
+ * The element whose id, or whose name attribute, is the given value, or null when there is none.
19
+ * @param {string} name
20
+ * @returns {PseudoElement|null}
21
+ */
22
+ namedItem(name: string): PseudoElement | null;
2
23
  }
@@ -4,10 +4,11 @@
4
4
  * @version 1.0.0
5
5
  */
6
6
  import { PseudoNode } from '../interfaces/PseudoNode';
7
- import { NodeService } from './NodeService';
8
7
  import { PseudoElement } from '../interfaces/PseudoElement';
8
+ import { NodeService } from './NodeService';
9
9
  import { PseudoNamedNodeMap } from '../interfaces/PseudoNamedNodeMap';
10
10
  import { PseudoDOMTokenList } from '../interfaces/PseudoDOMTokenList';
11
+ import { PseudoHTMLCollection } from '../interfaces/PseudoHTMLCollection';
11
12
  type attribute = {
12
13
  name: string;
13
14
  value: any;
@@ -80,6 +81,68 @@ export declare class ElementService extends NodeService implements Partial<Pseud
80
81
  * Some elements have default behaviour, this registers it when the element is added.
81
82
  * @returns {Function}
82
83
  */
84
+ /**
85
+ * A live view of this element's element children (text, comments and the like are not included).
86
+ * @returns {PseudoHTMLCollection}
87
+ */
88
+ get children(): PseudoHTMLCollection;
89
+ /**
90
+ * How many element children this element has.
91
+ * @returns {number}
92
+ */
93
+ get childElementCount(): number;
94
+ /**
95
+ * The first child of this element which is an element, or null when there is none.
96
+ * @returns {PseudoElement|null}
97
+ */
98
+ get firstElementChild(): PseudoElement | null;
99
+ /**
100
+ * The last child of this element which is an element, or null when there is none.
101
+ * @returns {PseudoElement|null}
102
+ */
103
+ get lastElementChild(): PseudoElement | null;
104
+ /**
105
+ * The sibling after this one which is an element, or null when there is none.
106
+ * @returns {PseudoElement|null}
107
+ */
108
+ get nextElementSibling(): PseudoElement | null;
109
+ /**
110
+ * The sibling before this one which is an element, or null when there is none.
111
+ * @returns {PseudoElement|null}
112
+ */
113
+ get previousElementSibling(): PseudoElement | null;
114
+ /**
115
+ * Put an element at a position relative to this one: beforebegin (before this element, as its previous sibling),
116
+ * afterbegin (as this element's first child), beforeend (as this element's last child) or afterend (after this
117
+ * element, as its next sibling).
118
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
119
+ * @param {ElementService} element The element to insert
120
+ * @returns {ElementService|null} The inserted element, or null when the position needed a parent this element does not have
121
+ * @throws {Error} When the position is not one of the four above
122
+ */
123
+ insertAdjacentElement(position: string, element: PseudoElement): PseudoElement | null;
124
+ /**
125
+ * Put text at a position relative to this element, the same as insertAdjacentElement but the text becomes a text node.
126
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
127
+ * @param {string} text The text to insert
128
+ * @throws {Error} When the position is not one of the four above
129
+ */
130
+ insertAdjacentText(position: string, text: string): void;
131
+ /**
132
+ * Shared implementation for insertAdjacentElement / insertAdjacentText.
133
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
134
+ * @param {PseudoNode|string} node The node (or text) to insert
135
+ * @returns {PseudoNode|null} The inserted node, or null when the position needed a parent this element does not have
136
+ * @throws {Error} When the position is not one of the four above
137
+ */
138
+ private insertAdjacent;
139
+ /**
140
+ * Not implemented yet (HTML parsing is out of scope for now).
141
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
142
+ * @param {string} text The markup which would be parsed
143
+ * @throws {Error}
144
+ */
145
+ insertAdjacentHTML(position: string, text: string): void;
83
146
  applyDefaultEvent(): Function;
84
147
  /**
85
148
  * An element which is added as a child gets its default events (for example a submit button submits its form).
@@ -23,6 +23,7 @@ const AttrService_1 = require('./AttrService')
23
23
  const DOMTokenListService_1 = require('./DOMTokenListService')
24
24
  const NamedNodeMapService_1 = require('./NamedNodeMapService')
25
25
  const getParentNodesFromAttribute_1 = __importDefault(require('../functions/getParentNodesFromAttribute'))
26
+ const HTMLCollectionService_1 = require('./HTMLCollectionService')
26
27
  const cloneObject_1 = __importDefault(require('si-funciona/dist/helpers/objects/cloneObject'))
27
28
  const isEqual_1 = __importDefault(require('si-funciona/dist/helpers/objects/isEqual'))
28
29
  /**
@@ -184,6 +185,128 @@ class ElementService extends NodeService_1.NodeService {
184
185
  * Some elements have default behaviour, this registers it when the element is added.
185
186
  * @returns {Function}
186
187
  */
188
+ /**
189
+ * A live view of this element's element children (text, comments and the like are not included).
190
+ * @returns {PseudoHTMLCollection}
191
+ */
192
+ get children () {
193
+ return new HTMLCollectionService_1.HTMLCollectionService(this)
194
+ }
195
+
196
+ /**
197
+ * How many element children this element has.
198
+ * @returns {number}
199
+ */
200
+ get childElementCount () {
201
+ return this.children.length
202
+ }
203
+
204
+ /**
205
+ * The first child of this element which is an element, or null when there is none.
206
+ * @returns {PseudoElement|null}
207
+ */
208
+ get firstElementChild () {
209
+ return this.children.item(0)
210
+ }
211
+
212
+ /**
213
+ * The last child of this element which is an element, or null when there is none.
214
+ * @returns {PseudoElement|null}
215
+ */
216
+ get lastElementChild () {
217
+ const elementChildren = this.children
218
+ return elementChildren.item(elementChildren.length - 1)
219
+ }
220
+
221
+ /**
222
+ * The sibling after this one which is an element, or null when there is none.
223
+ * @returns {PseudoElement|null}
224
+ */
225
+ get nextElementSibling () {
226
+ let sibling = this.nextSibling
227
+ while (sibling && sibling.nodeType !== NodeService_1.NodeService.ELEMENT_NODE) {
228
+ sibling = sibling.nextSibling
229
+ }
230
+ return sibling
231
+ }
232
+
233
+ /**
234
+ * The sibling before this one which is an element, or null when there is none.
235
+ * @returns {PseudoElement|null}
236
+ */
237
+ get previousElementSibling () {
238
+ let sibling = this.previousSibling
239
+ while (sibling && sibling.nodeType !== NodeService_1.NodeService.ELEMENT_NODE) {
240
+ sibling = sibling.previousSibling
241
+ }
242
+ return sibling
243
+ }
244
+
245
+ /**
246
+ * Put an element at a position relative to this one: beforebegin (before this element, as its previous sibling),
247
+ * afterbegin (as this element's first child), beforeend (as this element's last child) or afterend (after this
248
+ * element, as its next sibling).
249
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
250
+ * @param {ElementService} element The element to insert
251
+ * @returns {ElementService|null} The inserted element, or null when the position needed a parent this element does not have
252
+ * @throws {Error} When the position is not one of the four above
253
+ */
254
+ insertAdjacentElement (position, element) {
255
+ return this.insertAdjacent(position, element)
256
+ }
257
+
258
+ /**
259
+ * Put text at a position relative to this element, the same as insertAdjacentElement but the text becomes a text node.
260
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
261
+ * @param {string} text The text to insert
262
+ * @throws {Error} When the position is not one of the four above
263
+ */
264
+ insertAdjacentText (position, text) {
265
+ this.insertAdjacent(position, text)
266
+ }
267
+
268
+ /**
269
+ * Shared implementation for insertAdjacentElement / insertAdjacentText.
270
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
271
+ * @param {PseudoNode|string} node The node (or text) to insert
272
+ * @returns {PseudoNode|null} The inserted node, or null when the position needed a parent this element does not have
273
+ * @throws {Error} When the position is not one of the four above
274
+ */
275
+ insertAdjacent (position, node) {
276
+ switch (position) {
277
+ case 'beforebegin':
278
+ if (!this.parentNode) {
279
+ return null
280
+ }
281
+ this.before(node)
282
+ return node
283
+ case 'afterbegin':
284
+ this.prepend(node)
285
+ return node
286
+ case 'beforeend':
287
+ this.append(node)
288
+ return node
289
+ case 'afterend':
290
+ if (!this.parentNode) {
291
+ return null
292
+ }
293
+ this.after(node)
294
+ return node
295
+ default:
296
+ throw new Error(`"${position}" is not one of beforebegin, afterbegin, beforeend or afterend.`)
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Not implemented yet (HTML parsing is out of scope for now).
302
+ * @param {string} position beforebegin, afterbegin, beforeend or afterend
303
+ * @param {string} text The markup which would be parsed
304
+ * @throws {Error}
305
+ */
306
+ insertAdjacentHTML (position, text) {
307
+ throw new Error('ElementService.insertAdjacentHTML() is not implemented yet.')
308
+ }
309
+
187
310
  applyDefaultEvent () {
188
311
  let callback = event => undefined
189
312
  if (this.defaultEventApplied) {
@@ -1 +1 @@
1
- "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.every.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")),cloneObject_1=__importDefault(require("si-funciona/dist/helpers/objects/cloneObject")),isEqual_1=__importDefault(require("si-funciona/dist/helpers/objects/isEqual"));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)}currentAttributes(){return this.attributeList.map(({name:e,value:t})=>({name:e,value:this.propertyAttributes.indexOf(e)>=0?this[e]:t}))}get nodeName(){return this.tag}cloneShallow(){const e=new this.constructor({tagName:this.tag});return e.attributeList.length=0,this.currentAttributes().forEach(({name:t,value:r})=>{const i="object"==typeof r&&null!==r?(0,cloneObject_1.default)(r):r;e.attributeList.push({name:t,value:i}),e.propertyAttributes.indexOf(t)>=0&&(e[t]=i)}),e.ownerDocumentStore=this.ownerDocumentStore,e}equalsShallow(e){const t=this.currentAttributes(),r=e.currentAttributes();return this.nodeName===e.nodeName&&t.length===r.length&&t.every(({name:e,value:t})=>{const i=r.find(t=>t.name===e);return void 0!==i&&(0,isEqual_1.default)(t,i.value)})}get tagName(){return this.tag}get nodeType(){return NodeService_1.NodeService.ELEMENT_NODE}get attributes(){return new NamedNodeMapService_1.NamedNodeMapService(this.currentAttributes().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.currentAttributes().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.every.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")),HTMLCollectionService_1=require("./HTMLCollectionService"),cloneObject_1=__importDefault(require("si-funciona/dist/helpers/objects/cloneObject")),isEqual_1=__importDefault(require("si-funciona/dist/helpers/objects/isEqual"));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)}currentAttributes(){return this.attributeList.map(({name:e,value:t})=>({name:e,value:this.propertyAttributes.indexOf(e)>=0?this[e]:t}))}get nodeName(){return this.tag}cloneShallow(){const e=new this.constructor({tagName:this.tag});return e.attributeList.length=0,this.currentAttributes().forEach(({name:t,value:r})=>{const i="object"==typeof r&&null!==r?(0,cloneObject_1.default)(r):r;e.attributeList.push({name:t,value:i}),e.propertyAttributes.indexOf(t)>=0&&(e[t]=i)}),e.ownerDocumentStore=this.ownerDocumentStore,e}equalsShallow(e){const t=this.currentAttributes(),r=e.currentAttributes();return this.nodeName===e.nodeName&&t.length===r.length&&t.every(({name:e,value:t})=>{const i=r.find(t=>t.name===e);return void 0!==i&&(0,isEqual_1.default)(t,i.value)})}get tagName(){return this.tag}get nodeType(){return NodeService_1.NodeService.ELEMENT_NODE}get attributes(){return new NamedNodeMapService_1.NamedNodeMapService(this.currentAttributes().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}get children(){return new HTMLCollectionService_1.HTMLCollectionService(this)}get childElementCount(){return this.children.length}get firstElementChild(){return this.children.item(0)}get lastElementChild(){const e=this.children;return e.item(e.length-1)}get nextElementSibling(){let e=this.nextSibling;for(;e&&e.nodeType!==NodeService_1.NodeService.ELEMENT_NODE;)e=e.nextSibling;return e}get previousElementSibling(){let e=this.previousSibling;for(;e&&e.nodeType!==NodeService_1.NodeService.ELEMENT_NODE;)e=e.previousSibling;return e}insertAdjacentElement(e,t){return this.insertAdjacent(e,t)}insertAdjacentText(e,t){this.insertAdjacent(e,t)}insertAdjacent(e,t){switch(e){case"beforebegin":return this.parentNode?(this.before(t),t):null;case"afterbegin":return this.prepend(t),t;case"beforeend":return this.append(t),t;case"afterend":return this.parentNode?(this.after(t),t):null;default:throw new Error(`"${e}" is not one of beforebegin, afterbegin, beforeend or afterend.`)}}insertAdjacentHTML(e,t){throw new Error("ElementService.insertAdjacentHTML() is not implemented yet.")}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.currentAttributes().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,3 +1,49 @@
1
+ /**
2
+ * @file Substitute for the DOM HTMLCollection Class.
3
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
4
+ * @version 1.0.0
5
+ */
6
+ import { NodeService } from './NodeService';
1
7
  import { PseudoHTMLCollection } from '../interfaces/PseudoHTMLCollection';
8
+ /**
9
+ * Simulate the behaviour of the HTMLCollection Class when there is no DOM available: a live view of the element
10
+ * children of a node, recomputed from its childNodes each time it is used rather than kept in sync as they change.
11
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
12
+ * @class
13
+ */
2
14
  export declare class HTMLCollectionService implements PseudoHTMLCollection {
15
+ private readonly owner;
16
+ /**
17
+ * @param {NodeService} owner The node whose element children this is a live view of
18
+ * @constructor
19
+ */
20
+ constructor(owner: NodeService);
21
+ /**
22
+ * The current element children of the owner, in order.
23
+ * @returns {Array<PseudoNode>}
24
+ */
25
+ private elements;
26
+ /**
27
+ * How many elements are in the collection right now.
28
+ * @returns {number}
29
+ */
30
+ get length(): number;
31
+ /**
32
+ * The element at the given index, or null when there is none.
33
+ * @param {number} index
34
+ * @returns {*}
35
+ */
36
+ item(index: number): any | null;
37
+ /**
38
+ * The element whose id, or (failing that) whose name attribute, is the given value, or null when there is none.
39
+ * @param {string} name
40
+ * @returns {*}
41
+ */
42
+ namedItem(name: string): any | null;
43
+ /**
44
+ * Iterate over the current element children.
45
+ * @returns {Iterator}
46
+ */
47
+ [Symbol.iterator](): Iterator<any>;
3
48
  }
49
+ export default HTMLCollectionService;
@@ -1,8 +1,75 @@
1
1
  'use strict'
2
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')
3
6
  Object.defineProperty(exports, '__esModule', {
4
7
  value: true
5
8
  })
6
9
  exports.HTMLCollectionService = void 0
7
- class HTMLCollectionService {}
10
+ /**
11
+ * @file Substitute for the DOM HTMLCollection Class.
12
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
13
+ * @version 1.0.0
14
+ */
15
+ const NodeService_1 = require('./NodeService')
16
+ /**
17
+ * Simulate the behaviour of the HTMLCollection Class when there is no DOM available: a live view of the element
18
+ * children of a node, recomputed from its childNodes each time it is used rather than kept in sync as they change.
19
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
20
+ * @class
21
+ */
22
+ class HTMLCollectionService {
23
+ /**
24
+ * @param {NodeService} owner The node whose element children this is a live view of
25
+ * @constructor
26
+ */
27
+ constructor (owner) {
28
+ this.owner = owner
29
+ }
30
+
31
+ /**
32
+ * The current element children of the owner, in order.
33
+ * @returns {Array<PseudoNode>}
34
+ */
35
+ elements () {
36
+ return Array.from(this.owner.childNodes).filter(node => node.nodeType === NodeService_1.NodeService.ELEMENT_NODE)
37
+ }
38
+
39
+ /**
40
+ * How many elements are in the collection right now.
41
+ * @returns {number}
42
+ */
43
+ get length () {
44
+ return this.elements().length
45
+ }
46
+
47
+ /**
48
+ * The element at the given index, or null when there is none.
49
+ * @param {number} index
50
+ * @returns {*}
51
+ */
52
+ item (index) {
53
+ return this.elements()[index] || null
54
+ }
55
+
56
+ /**
57
+ * The element whose id, or (failing that) whose name attribute, is the given value, or null when there is none.
58
+ * @param {string} name
59
+ * @returns {*}
60
+ */
61
+ namedItem (name) {
62
+ const elements = this.elements()
63
+ return elements.find(element => element.id === name) || elements.find(element => element.getAttribute('name') === name) || null
64
+ }
65
+
66
+ /**
67
+ * Iterate over the current element children.
68
+ * @returns {Iterator}
69
+ */
70
+ [Symbol.iterator] () {
71
+ return this.elements()[Symbol.iterator]()
72
+ }
73
+ }
8
74
  exports.HTMLCollectionService = HTMLCollectionService
75
+ exports.default = HTMLCollectionService
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.HTMLCollectionService=void 0;class HTMLCollectionService{}exports.HTMLCollectionService=HTMLCollectionService;
1
+ "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.find.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.HTMLCollectionService=void 0;const NodeService_1=require("./NodeService");class HTMLCollectionService{constructor(e){this.owner=e}elements(){return Array.from(this.owner.childNodes).filter(e=>e.nodeType===NodeService_1.NodeService.ELEMENT_NODE)}get length(){return this.elements().length}item(e){return this.elements()[e]||null}namedItem(e){const t=this.elements();return t.find(t=>t.id===e)||t.find(t=>t.getAttribute("name")===e)||null}[Symbol.iterator](){return this.elements()[Symbol.iterator]()}}exports.HTMLCollectionService=HTMLCollectionService,exports.default=HTMLCollectionService;
@@ -36,7 +36,8 @@ export declare class NodeService extends EventTargetService implements PseudoNod
36
36
  static readonly DOCUMENT_POSITION_CONTAINED_BY = 16;
37
37
  static readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32;
38
38
  private static nextNodeId;
39
- children: PseudoNodeList | LinkedTreeList;
39
+ /** The raw list of every child node (all types), used to implement childNodes/firstChild/lastChild/insertBefore/removeChild. Not the same thing as Element.children (an HTMLCollection of just the element children). */
40
+ protected childList: PseudoNodeList | LinkedTreeList;
40
41
  parent: PseudoNode | null;
41
42
  protected nodeNameValue: string;
42
43
  private nodeValueStore;
@@ -91,6 +92,53 @@ export declare class NodeService extends EventTargetService implements PseudoNod
91
92
  * @returns {boolean}
92
93
  */
93
94
  protected equalsShallow(other: NodeService): boolean;
95
+ /**
96
+ * Add nodes (strings become text nodes) as the last children of this node, in the order given.
97
+ * @param {...(PseudoNode|string)} nodes The nodes (or text) to add
98
+ * @throws {Error} When this kind of node cannot have children
99
+ */
100
+ append(...nodes: Array<PseudoNode | string>): void;
101
+ /**
102
+ * Add nodes (strings become text nodes) as the first children of this node, in the order given.
103
+ * @param {...(PseudoNode|string)} nodes The nodes (or text) to add
104
+ * @throws {Error} When this kind of node cannot have children
105
+ */
106
+ prepend(...nodes: Array<PseudoNode | string>): void;
107
+ /**
108
+ * Remove every child of this node and put the given nodes (strings become text nodes) in their place, in order.
109
+ * @param {...(PseudoNode|string)} nodes The nodes (or text) to add
110
+ * @throws {Error} When this kind of node cannot have children
111
+ */
112
+ replaceChildren(...nodes: Array<PseudoNode | string>): void;
113
+ /**
114
+ * Add nodes (strings become text nodes) as this node's previous siblings, in order. Does nothing when this node has
115
+ * no parent.
116
+ * @param {...(PseudoNode|string)} nodes The nodes (or text) to add
117
+ */
118
+ before(...nodes: Array<PseudoNode | string>): void;
119
+ /**
120
+ * Add nodes (strings become text nodes) as this node's next siblings, in order. Does nothing when this node has no
121
+ * parent.
122
+ * @param {...(PseudoNode|string)} nodes The nodes (or text) to add
123
+ */
124
+ after(...nodes: Array<PseudoNode | string>): void;
125
+ /**
126
+ * Put the given nodes (strings become text nodes) where this node is, in order, then remove this node. Does nothing
127
+ * when this node has no parent.
128
+ * @param {...(PseudoNode|string)} nodes The nodes (or text) to put in this node's place
129
+ */
130
+ replaceWith(...nodes: Array<PseudoNode | string>): void;
131
+ /**
132
+ * Remove this node from its parent. Does nothing when it has no parent.
133
+ */
134
+ remove(): void;
135
+ /**
136
+ * Turn a value given to append / prepend / before / after / replaceWith / replaceChildren into a node: a string
137
+ * becomes a text node belonging to this node's document, anything else is returned as it is.
138
+ * @param {PseudoNode|string} value The value to add
139
+ * @returns {PseudoNode}
140
+ */
141
+ private toChildNode;
94
142
  /**
95
143
  * Called each time a node has been inserted as a child of this node, so that nodes which need to react to children
96
144
  * (for example elements applying default events) can do so.