pseudo-dom 0.1.0 → 0.2.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 (31) hide show
  1. package/README.md +496 -72
  2. package/browser/pseudo-dom.js +619 -284
  3. package/browser/pseudo-dom.min.js +1 -1
  4. package/dist/classes/PseudoHTMLDocument.d.ts +2 -2
  5. package/dist/classes/PseudoHTMLDocument.js +10 -21
  6. package/dist/classes/PseudoHTMLDocument.min.js +1 -1
  7. package/dist/classes/PseudoNodeList.js +14 -8
  8. package/dist/classes/PseudoNodeList.min.js +1 -1
  9. package/dist/factories/generateNode.d.ts +2 -10
  10. package/dist/factories/generateNode.js +9 -42
  11. package/dist/factories/generateNode.min.js +1 -1
  12. package/dist/functions/getParentNodes.d.ts +8 -6
  13. package/dist/functions/getParentNodes.js +16 -9
  14. package/dist/functions/getParentNodes.min.js +1 -1
  15. package/dist/functions/getParentNodesFromAttribute.d.ts +7 -7
  16. package/dist/functions/getParentNodesFromAttribute.js +21 -1
  17. package/dist/functions/getParentNodesFromAttribute.min.js +1 -1
  18. package/dist/functions.d.ts +1 -1
  19. package/dist/services/DocumentFragmentService.d.ts +9 -0
  20. package/dist/services/DocumentFragmentService.js +16 -1
  21. package/dist/services/DocumentFragmentService.min.js +1 -1
  22. package/dist/services/DocumentService.d.ts +8 -0
  23. package/dist/services/DocumentService.js +15 -1
  24. package/dist/services/DocumentService.min.js +1 -1
  25. package/dist/services/ElementService.d.ts +5 -6
  26. package/dist/services/ElementService.js +17 -13
  27. package/dist/services/ElementService.min.js +1 -1
  28. package/dist/services/NodeService.d.ts +31 -16
  29. package/dist/services/NodeService.js +90 -33
  30. package/dist/services/NodeService.min.js +1 -1
  31. package/package.json +2 -2
@@ -3,30 +3,22 @@ import { NodeService } from '../services/NodeService';
3
3
  import { PseudoNode } from '../interfaces/PseudoNode';
4
4
  import { PseudoElement } from '../interfaces/PseudoElement';
5
5
  /**
6
- * A node which is stored in a TreeLinker and answers questions about its position in the tree by asking that linker.
6
+ * A node which is stored in a TreeLinker (for example by a list built from an array of values). It finds its siblings
7
+ * from that linker, and its parent from the linker's parent when it has not been given one by appendChild.
7
8
  * @author Joshua Heagle <joshuaheagle@gmail.com>
8
9
  * @class
9
10
  * @augments NodeService
10
11
  */
11
12
  export declare class LinkedNode extends NodeService {
12
- private readonly linker;
13
13
  /**
14
14
  * @param {TreeLinker} linker The linker holding this node
15
15
  * @param {string|null} value The value of the node
16
16
  * @constructor
17
17
  */
18
18
  constructor(linker: TreeLinker, value?: string | null);
19
- get childNodes(): any;
20
- get firstChild(): PseudoNode | null;
21
19
  get isConnected(): boolean;
22
- get lastChild(): PseudoNode | null;
23
- get nextSibling(): PseudoNode | null;
24
- get ownerDocument(): any;
25
20
  get parentNode(): PseudoNode | null;
26
21
  get parentElement(): PseudoElement | null;
27
- get previousSibling(): PseudoNode | null;
28
- appendChild(childNode: PseudoNode): PseudoNode;
29
- getRootNode(): PseudoNode;
30
22
  }
31
23
  export declare class NodeFactory extends TreeLinker {
32
24
  }
@@ -9,7 +9,8 @@ exports.NodeFactory = exports.LinkedNode = void 0
9
9
  const TreeLinker_1 = require('collect-your-stuff/dist/collections/linked-tree-list/TreeLinker')
10
10
  const NodeService_1 = require('../services/NodeService')
11
11
  /**
12
- * A node which is stored in a TreeLinker and answers questions about its position in the tree by asking that linker.
12
+ * A node which is stored in a TreeLinker (for example by a list built from an array of values). It finds its siblings
13
+ * from that linker, and its parent from the linker's parent when it has not been given one by appendChild.
13
14
  * @author Joshua Heagle <joshuaheagle@gmail.com>
14
15
  * @class
15
16
  * @augments NodeService
@@ -22,60 +23,26 @@ class LinkedNode extends NodeService_1.NodeService {
22
23
  */
23
24
  constructor (linker, value = '') {
24
25
  super()
25
- this.linker = linker
26
+ this.listLinker = linker
26
27
  this.nodeValue = value
27
28
  }
28
29
 
29
- get childNodes () {
30
- return this.linker.children
31
- }
32
-
33
- get firstChild () {
34
- const children = this.linker.children
35
- return children && children.first ? children.first.data : null
36
- }
37
-
38
30
  get isConnected () {
39
- return !!this.linker.parent
40
- }
41
-
42
- get lastChild () {
43
- const children = this.linker.children
44
- return children && children.last ? children.last.data : null
45
- }
46
-
47
- get nextSibling () {
48
- return this.linker.next ? this.linker.next.data : null
49
- }
50
-
51
- get ownerDocument () {
52
- const root = this.linker.parent ? this.linker.rootParent : null
53
- return root ? root.data : null
31
+ return !!this.parentNode
54
32
  }
55
33
 
56
34
  get parentNode () {
57
- return this.linker.parent ? this.linker.parent.data : null
35
+ if (this.parent) {
36
+ return this.parent
37
+ }
38
+ const parentLinker = this.listLinker ? this.listLinker.parent : null
39
+ return parentLinker ? parentLinker.data : null
58
40
  }
59
41
 
60
42
  get parentElement () {
61
43
  const parent = this.parentNode
62
44
  return parent && parent.nodeType === NodeService_1.NodeService.ELEMENT_NODE ? parent : null
63
45
  }
64
-
65
- get previousSibling () {
66
- return this.linker.prev ? this.linker.prev.data : null
67
- }
68
-
69
- appendChild (childNode) {
70
- this.linker.next = childNode
71
- childNode.prev = this.linker
72
- return childNode
73
- }
74
-
75
- getRootNode () {
76
- const root = this.linker.rootParent
77
- return root ? root.data : this
78
- }
79
46
  }
80
47
  exports.LinkedNode = LinkedNode
81
48
  class NodeFactory extends TreeLinker_1.TreeLinker {}
@@ -1 +1 @@
1
- "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.NodeFactory=exports.LinkedNode=void 0;const TreeLinker_1=require("collect-your-stuff/dist/collections/linked-tree-list/TreeLinker"),NodeService_1=require("../services/NodeService");class LinkedNode extends NodeService_1.NodeService{constructor(e,t=""){super(),this.linker=e,this.nodeValue=t}get childNodes(){return this.linker.children}get firstChild(){const e=this.linker.children;return e&&e.first?e.first.data:null}get isConnected(){return!!this.linker.parent}get lastChild(){const e=this.linker.children;return e&&e.last?e.last.data:null}get nextSibling(){return this.linker.next?this.linker.next.data:null}get ownerDocument(){const e=this.linker.parent?this.linker.rootParent:null;return e?e.data:null}get parentNode(){return this.linker.parent?this.linker.parent.data:null}get parentElement(){const e=this.parentNode;return e&&e.nodeType===NodeService_1.NodeService.ELEMENT_NODE?e:null}get previousSibling(){return this.linker.prev?this.linker.prev.data:null}appendChild(e){return this.linker.next=e,e.prev=this.linker,e}getRootNode(){const e=this.linker.rootParent;return e?e.data:this}}exports.LinkedNode=LinkedNode;class NodeFactory extends TreeLinker_1.TreeLinker{}exports.NodeFactory=NodeFactory;const generateNode=()=>(NodeFactory.fromArray=(e=[],t=NodeFactory)=>e.reduce((e,r)=>{"object"!=typeof r&&(r={data:r});const n=new t(Object.assign({},r,{prev:e.tail}));return n.data=new LinkedNode(n,r.data),null===e.head?{head:n,tail:n}:(e.tail.next=n,n.prev=e.tail,{head:e.head,tail:n})},{head:null,tail:null}),NodeFactory);exports.default=generateNode;
1
+ "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.NodeFactory=exports.LinkedNode=void 0;const TreeLinker_1=require("collect-your-stuff/dist/collections/linked-tree-list/TreeLinker"),NodeService_1=require("../services/NodeService");class LinkedNode extends NodeService_1.NodeService{constructor(e,t=""){super(),this.listLinker=e,this.nodeValue=t}get isConnected(){return!!this.parentNode}get parentNode(){if(this.parent)return this.parent;const e=this.listLinker?this.listLinker.parent:null;return e?e.data:null}get parentElement(){const e=this.parentNode;return e&&e.nodeType===NodeService_1.NodeService.ELEMENT_NODE?e:null}}exports.LinkedNode=LinkedNode;class NodeFactory extends TreeLinker_1.TreeLinker{}exports.NodeFactory=NodeFactory;const generateNode=()=>(NodeFactory.fromArray=(e=[],t=NodeFactory)=>e.reduce((e,r)=>{"object"!=typeof r&&(r={data:r});const o=new t(Object.assign({},r,{prev:e.tail}));return o.data=new LinkedNode(o,r.data),null===e.head?{head:o,tail:o}:(e.tail.next=o,o.prev=e.tail,{head:e.head,tail:o})},{head:null,tail:null}),NodeFactory);exports.default=generateNode;
@@ -1,9 +1,11 @@
1
- /**
2
- * A helper selector function for retrieving all parent PseudoNode for the given child node.
3
- * @param {PseudoNode} node
4
- * @returns {Array.<PseudoNode>}
5
- */
6
1
  import { PseudoNode } from '../interfaces/PseudoNode';
7
2
  import { PseudoEventTarget } from '../interfaces/PseudoEventTarget';
8
- declare const getParentNodes: (node: PseudoEventTarget) => Array<PseudoNode>;
3
+ /**
4
+ * Get all of the ancestors of a node, starting with the root of the tree and ending with the node's own parent (the
5
+ * order in which an event travels down through them). A node which has no parent has no ancestors.
6
+ * @function getParentNodes
7
+ * @param {PseudoEventTarget|PseudoNode|*} node The node to find the ancestors of
8
+ * @returns {Array<PseudoNode>}
9
+ */
10
+ declare const getParentNodes: (node: PseudoEventTarget | PseudoNode | any) => Array<PseudoNode>;
9
11
  export default getParentNodes;
@@ -1,15 +1,22 @@
1
1
  'use strict'
2
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
3
  Object.defineProperty(exports, '__esModule', {
11
4
  value: true
12
5
  })
13
- const getParentNodesFromAttribute_1 = __importDefault(require('./getParentNodesFromAttribute'))
14
- const getParentNodes = node => (0, getParentNodesFromAttribute_1.default)('', false, node)
6
+ /**
7
+ * Get all of the ancestors of a node, starting with the root of the tree and ending with the node's own parent (the
8
+ * order in which an event travels down through them). A node which has no parent has no ancestors.
9
+ * @function getParentNodes
10
+ * @param {PseudoEventTarget|PseudoNode|*} node The node to find the ancestors of
11
+ * @returns {Array<PseudoNode>}
12
+ */
13
+ const getParentNodes = node => {
14
+ const parents = []
15
+ let current = node && node.parentNode ? node.parentNode : null
16
+ while (current) {
17
+ parents.unshift(current)
18
+ current = current.parentNode
19
+ }
20
+ return parents
21
+ }
15
22
  exports.default = getParentNodes
@@ -1 +1 @@
1
- "use strict";var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const getParentNodesFromAttribute_1=__importDefault(require("./getParentNodesFromAttribute")),getParentNodes=e=>(0,getParentNodesFromAttribute_1.default)("",!1,e);exports.default=getParentNodes;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});const getParentNodes=e=>{const t=[];let r=e&&e.parentNode?e.parentNode:null;for(;r;)t.unshift(r),r=r.parentNode;return t};exports.default=getParentNodes;
@@ -1,14 +1,14 @@
1
+ import { PseudoNode } from '../interfaces/PseudoNode';
2
+ import { PseudoEventTarget } from '../interfaces/PseudoEventTarget';
1
3
  /**
2
4
  * A selector function for retrieving existing parent PseudoNode from the given child item.
3
5
  * This function will check all the parents starting from node, and scan the attributes
4
- * property for matches. The return array contains all matching parent ancestors.
5
- * WARNING: This is a recursive function.
6
- * @param {string} attr
7
- * @param {number|string} value
8
- * @param {PseudoNode} node
6
+ * property for matches. The return array contains all matching parent ancestors, starting with the root of the tree.
7
+ * @function getParentNodesFromAttribute
8
+ * @param {string} attr The property to compare on each ancestor (a missing property counts as false)
9
+ * @param {boolean|number|string} value The value the property must have
10
+ * @param {PseudoEventTarget|PseudoNode|*} node The node to find the matching ancestors of
9
11
  * @returns {Array.<PseudoNode>}
10
12
  */
11
- import { PseudoNode } from '../interfaces/PseudoNode';
12
- import { PseudoEventTarget } from '../interfaces/PseudoEventTarget';
13
13
  declare const getParentNodesFromAttribute: (attr: string, value: boolean | number | string, node: PseudoEventTarget | PseudoNode | any) => Array<PseudoNode>;
14
14
  export default getParentNodesFromAttribute;
@@ -1,9 +1,29 @@
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
+ const __importDefault = void 0 && (void 0).__importDefault || function (mod) {
6
+ return mod && mod.__esModule
7
+ ? mod
8
+ : {
9
+ default: mod
10
+ }
11
+ }
3
12
  Object.defineProperty(exports, '__esModule', {
4
13
  value: true
5
14
  })
15
+ const getParentNodes_1 = __importDefault(require('./getParentNodes'))
16
+ /**
17
+ * A selector function for retrieving existing parent PseudoNode from the given child item.
18
+ * This function will check all the parents starting from node, and scan the attributes
19
+ * property for matches. The return array contains all matching parent ancestors, starting with the root of the tree.
20
+ * @function getParentNodesFromAttribute
21
+ * @param {string} attr The property to compare on each ancestor (a missing property counts as false)
22
+ * @param {boolean|number|string} value The value the property must have
23
+ * @param {PseudoEventTarget|PseudoNode|*} node The node to find the matching ancestors of
24
+ * @returns {Array.<PseudoNode>}
25
+ */
6
26
  const getParentNodesFromAttribute = (attr, value, node) => {
7
- return Object.keys(node.parentNode).length ? (node.parentNode[attr] || false) === value ? getParentNodesFromAttribute(attr, value, node.parentNode).concat([node.parentNode]) : getParentNodesFromAttribute(attr, value, node.parentNode) : []
27
+ return (0, getParentNodes_1.default)(node).filter(parent => (parent[attr] || false) === value)
8
28
  }
9
29
  exports.default = getParentNodesFromAttribute
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});const getParentNodesFromAttribute=(e,t,r)=>Object.keys(r.parentNode).length?(r.parentNode[e]||!1)===t?getParentNodesFromAttribute(e,t,r.parentNode).concat([r.parentNode]):getParentNodesFromAttribute(e,t,r.parentNode):[];exports.default=getParentNodesFromAttribute;
1
+ "use strict";require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js");var __importDefault=function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const getParentNodes_1=__importDefault(require("./getParentNodes")),getParentNodesFromAttribute=(e,t,r)=>(0,getParentNodes_1.default)(r).filter(r=>(r[e]||!1)===t);exports.default=getParentNodesFromAttribute;
@@ -1,5 +1,5 @@
1
1
  declare const _default: {
2
- getParentNodes: (node: import("./interfaces/PseudoEventTarget").PseudoEventTarget) => Array<import("./interfaces/PseudoNode").PseudoNode>;
2
+ getParentNodes: (node: import("./interfaces/PseudoEventTarget").PseudoEventTarget | import("./interfaces/PseudoNode").PseudoNode | any) => Array<import("./interfaces/PseudoNode").PseudoNode>;
3
3
  getParentNodesFromAttribute: (attr: string, value: boolean | number | string, node: import("./interfaces/PseudoEventTarget").PseudoEventTarget | import("./interfaces/PseudoNode").PseudoNode | any) => Array<import("./interfaces/PseudoNode").PseudoNode>;
4
4
  };
5
5
  export default _default;
@@ -1,4 +1,13 @@
1
1
  import { NodeService } from './NodeService';
2
2
  import { PseudoDocumentFragment } from '../interfaces/PseudoDocumentFragment';
3
+ /**
4
+ * Simulate the behaviour of the DocumentFragment Class when there is no DOM available: a container for nodes which is
5
+ * not part of a tree, when it is inserted its children are moved into the tree instead.
6
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
7
+ * @class
8
+ * @augments NodeService
9
+ */
3
10
  export declare class DocumentFragmentService extends NodeService implements PseudoDocumentFragment {
11
+ get nodeName(): string;
12
+ get nodeType(): number;
4
13
  }
@@ -5,5 +5,20 @@ Object.defineProperty(exports, '__esModule', {
5
5
  })
6
6
  exports.DocumentFragmentService = void 0
7
7
  const NodeService_1 = require('./NodeService')
8
- class DocumentFragmentService extends NodeService_1.NodeService {}
8
+ /**
9
+ * Simulate the behaviour of the DocumentFragment Class when there is no DOM available: a container for nodes which is
10
+ * not part of a tree, when it is inserted its children are moved into the tree instead.
11
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
12
+ * @class
13
+ * @augments NodeService
14
+ */
15
+ class DocumentFragmentService extends NodeService_1.NodeService {
16
+ get nodeName () {
17
+ return '#document-fragment'
18
+ }
19
+
20
+ get nodeType () {
21
+ return NodeService_1.NodeService.DOCUMENT_FRAGMENT_NODE
22
+ }
23
+ }
9
24
  exports.DocumentFragmentService = DocumentFragmentService
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DocumentFragmentService=void 0;const NodeService_1=require("./NodeService");class DocumentFragmentService extends NodeService_1.NodeService{}exports.DocumentFragmentService=DocumentFragmentService;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DocumentFragmentService=void 0;const NodeService_1=require("./NodeService");class DocumentFragmentService extends NodeService_1.NodeService{get nodeName(){return"#document-fragment"}get nodeType(){return NodeService_1.NodeService.DOCUMENT_FRAGMENT_NODE}}exports.DocumentFragmentService=DocumentFragmentService;
@@ -1,4 +1,12 @@
1
1
  import { NodeService } from './NodeService';
2
2
  import { PseudoDocument } from '../interfaces/PseudoDocument';
3
+ /**
4
+ * Simulate the behaviour of the Document Class when there is no DOM available.
5
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
6
+ * @class
7
+ * @augments NodeService
8
+ */
3
9
  export declare class DocumentService extends NodeService implements PseudoDocument {
10
+ get nodeName(): string;
11
+ get nodeType(): number;
4
12
  }
@@ -5,5 +5,19 @@ Object.defineProperty(exports, '__esModule', {
5
5
  })
6
6
  exports.DocumentService = void 0
7
7
  const NodeService_1 = require('./NodeService')
8
- class DocumentService extends NodeService_1.NodeService {}
8
+ /**
9
+ * Simulate the behaviour of the Document Class when there is no DOM available.
10
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
11
+ * @class
12
+ * @augments NodeService
13
+ */
14
+ class DocumentService extends NodeService_1.NodeService {
15
+ get nodeName () {
16
+ return '#document'
17
+ }
18
+
19
+ get nodeType () {
20
+ return NodeService_1.NodeService.DOCUMENT_NODE
21
+ }
22
+ }
9
23
  exports.DocumentService = DocumentService
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DocumentService=void 0;const NodeService_1=require("./NodeService");class DocumentService extends NodeService_1.NodeService{}exports.DocumentService=DocumentService;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DocumentService=void 0;const NodeService_1=require("./NodeService");class DocumentService extends NodeService_1.NodeService{get nodeName(){return"#document"}get nodeType(){return NodeService_1.NodeService.DOCUMENT_NODE}}exports.DocumentService=DocumentService;
@@ -39,8 +39,8 @@ export declare class ElementService extends NodeService implements Partial<Pseud
39
39
  * @param {Object} [settings={}]
40
40
  * @param {string} [settings.tagName=''] The name of the tag this element represents
41
41
  * @param {Array<{name: string, value: *}>} [settings.attributes=[]] The attributes (also assigned as properties) to start with
42
- * @param {PseudoNode|null} [settings.parent=null] The parent node
43
- * @param {Array} [settings.children=[]] The values or nodes to start as children
42
+ * @param {PseudoNode|null} [settings.parent=null] The node to add this element to as its last child
43
+ * @param {Array<PseudoNode>} [settings.children=[]] The nodes to start as children
44
44
  * @constructor
45
45
  */
46
46
  constructor({ tagName, attributes, parent, children }?: {
@@ -61,11 +61,10 @@ export declare class ElementService extends NodeService implements Partial<Pseud
61
61
  */
62
62
  applyDefaultEvent(): Function;
63
63
  /**
64
- *
65
- * @param {PseudoNode|ElementService} childElement
66
- * @returns {PseudoNode}
64
+ * An element which is added as a child gets its default events (for example a submit button submits its form).
65
+ * @param {NodeService} child The node which was inserted
67
66
  */
68
- appendChild(childElement: ElementService): PseudoNode;
67
+ protected childInserted(child: NodeService): void;
69
68
  /**
70
69
  * Check whether the element has an attribute by that name.
71
70
  * @param {string} attributeName
@@ -16,8 +16,6 @@ Object.defineProperty(exports, '__esModule', {
16
16
  value: true
17
17
  })
18
18
  exports.ElementService = void 0
19
- const generateNodeList_1 = __importDefault(require('../factories/generateNodeList'))
20
- const TreeLinker_1 = require('collect-your-stuff/dist/collections/linked-tree-list/TreeLinker')
21
19
  const NodeService_1 = require('./NodeService')
22
20
  const AttrService_1 = require('./AttrService')
23
21
  const DOMTokenListService_1 = require('./DOMTokenListService')
@@ -43,8 +41,8 @@ class ElementService extends NodeService_1.NodeService {
43
41
  * @param {Object} [settings={}]
44
42
  * @param {string} [settings.tagName=''] The name of the tag this element represents
45
43
  * @param {Array<{name: string, value: *}>} [settings.attributes=[]] The attributes (also assigned as properties) to start with
46
- * @param {PseudoNode|null} [settings.parent=null] The parent node
47
- * @param {Array} [settings.children=[]] The values or nodes to start as children
44
+ * @param {PseudoNode|null} [settings.parent=null] The node to add this element to as its last child
45
+ * @param {Array<PseudoNode>} [settings.children=[]] The nodes to start as children
48
46
  * @constructor
49
47
  */
50
48
  constructor ({
@@ -55,8 +53,6 @@ class ElementService extends NodeService_1.NodeService {
55
53
  } = {}) {
56
54
  super()
57
55
  this.tokenList = new DOMTokenListService_1.DOMTokenListService()
58
- this.parent = parent
59
- this.children = (0, generateNodeList_1.default)(TreeLinker_1.TreeLinker.fromArray(children).head)
60
56
  this.tag = tagName
61
57
  this.attributeList = attributes.concat([{
62
58
  name: 'className',
@@ -77,6 +73,15 @@ class ElementService extends NodeService_1.NodeService {
77
73
  }) => {
78
74
  this[name] = value
79
75
  })
76
+ children.forEach(child => {
77
+ if (!child || typeof child.nodeType !== 'number') {
78
+ throw new TypeError('The children of an element must be nodes.')
79
+ }
80
+ this.appendChild(child)
81
+ })
82
+ if (parent) {
83
+ parent.appendChild(this)
84
+ }
80
85
  }
81
86
 
82
87
  get tagName () {
@@ -132,14 +137,13 @@ class ElementService extends NodeService_1.NodeService {
132
137
  }
133
138
 
134
139
  /**
135
- *
136
- * @param {PseudoNode|ElementService} childElement
137
- * @returns {PseudoNode}
140
+ * An element which is added as a child gets its default events (for example a submit button submits its form).
141
+ * @param {NodeService} child The node which was inserted
138
142
  */
139
- appendChild (childElement) {
140
- super.appendChild(childElement)
141
- childElement.applyDefaultEvent()
142
- return childElement
143
+ childInserted (child) {
144
+ if (typeof child.applyDefaultEvent === 'function') {
145
+ child.applyDefaultEvent()
146
+ }
143
147
  }
144
148
 
145
149
  /**
@@ -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 generateNodeList_1=__importDefault(require("../factories/generateNodeList")),TreeLinker_1=require("collect-your-stuff/dist/collections/linked-tree-list/TreeLinker"),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.parent=r,this.children=(0,generateNodeList_1.default)(TreeLinker_1.TreeLinker.fromArray(i).head),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})}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}appendChild(e){return super.appendChild(e),e.applyDefaultEvent(),e}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 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,5 +1,6 @@
1
1
  import { PseudoNodeList } from '../classes/PseudoNodeList';
2
2
  import { LinkedTreeList } from 'collect-your-stuff/dist/collections/linked-tree-list/LinkedTreeList';
3
+ import { TreeLinker } from 'collect-your-stuff/dist/collections/linked-tree-list/TreeLinker';
3
4
  import { PseudoNode } from '../interfaces/PseudoNode';
4
5
  import EventTargetService from './EventTargetService';
5
6
  import { PseudoElement } from '../interfaces/PseudoElement';
@@ -33,8 +34,8 @@ export declare class NodeService extends EventTargetService implements PseudoNod
33
34
  protected nodeNameValue: string;
34
35
  private nodeValueStore;
35
36
  private textContentStore;
36
- private next;
37
- private prev;
37
+ /** The linker which holds this node in the children list of its parent, from which its siblings are found (null while it has no parent). */
38
+ protected listLinker: TreeLinker | null;
38
39
  /**
39
40
  *
40
41
  * @constructor
@@ -57,11 +58,17 @@ export declare class NodeService extends EventTargetService implements PseudoNod
57
58
  get textContent(): string | null;
58
59
  set textContent(text: string | null);
59
60
  /**
60
- *
61
- * @param {PseudoNode} childNode
62
- * @returns {PseudoNode}
61
+ * Add a node as the last child of this node (a node which is already in a tree is moved).
62
+ * @param {PseudoNode} childNode The node to add
63
+ * @returns {PseudoNode} The added node
63
64
  */
64
65
  appendChild(childNode: PseudoNode): PseudoNode;
66
+ /**
67
+ * Called each time a node has been inserted as a child of this node, so that nodes which need to react to children
68
+ * (for example elements applying default events) can do so.
69
+ * @param {NodeService} child The node which was inserted
70
+ */
71
+ protected childInserted(child: NodeService): void;
65
72
  /**
66
73
  * Not implemented yet.
67
74
  * @throws {Error}
@@ -73,19 +80,24 @@ export declare class NodeService extends EventTargetService implements PseudoNod
73
80
  */
74
81
  compareDocumentPosition(otherNode: PseudoNode): number;
75
82
  /**
76
- * Not implemented yet.
77
- * @throws {Error}
83
+ * Check whether a node is this node or one of its descendants.
84
+ * @param {PseudoNode|null} otherNode The node to look for
85
+ * @returns {boolean}
78
86
  */
79
- contains(otherNode: PseudoNode): boolean;
87
+ contains(otherNode: PseudoNode | null): boolean;
80
88
  getRootNode(options?: {
81
89
  composed: boolean;
82
90
  }): PseudoNode;
83
91
  hasChildNodes(): boolean;
84
92
  /**
85
- * Not implemented yet.
86
- * @throws {Error}
93
+ * Insert a node as a child of this node, before the given child (or at the end when there is none). A node which is
94
+ * already in a tree is moved, and the children of a document fragment are moved in order.
95
+ * @param {PseudoNode} newNode The node to insert
96
+ * @param {PseudoNode|null} [referenceNode=null] The child of this node to insert before, or null to insert at the end
97
+ * @returns {PseudoNode} The inserted node
98
+ * @throws {Error} When the reference node is not a child of this node, or the new node is this node or contains it
87
99
  */
88
- insertBefore(newNode: PseudoNode, referenceNode: PseudoNode | null): PseudoNode | PseudoDocumentFragment;
100
+ insertBefore(newNode: PseudoNode, referenceNode?: PseudoNode | null): PseudoNode | PseudoDocumentFragment;
89
101
  isDefaultNamespace(namespaceURI: string | null): boolean;
90
102
  /**
91
103
  * Not implemented yet.
@@ -97,15 +109,18 @@ export declare class NodeService extends EventTargetService implements PseudoNod
97
109
  lookupNamespaceURI(prefix: string): string | null;
98
110
  normalize(): void;
99
111
  /**
100
- * Remove the given child from this node.
101
- * @param {PseudoNode} childElement The child node, or its TreeLinker from the children list
102
- * @returns {PseudoNode}
112
+ * Remove a child from this node, it no longer has a parent or siblings afterwards.
113
+ * @param {PseudoNode} childElement The child node to remove
114
+ * @returns {PseudoNode} The removed node
103
115
  * @throws {Error} When the node is not a child of this node
104
116
  */
105
117
  removeChild(childElement: PseudoNode): PseudoNode;
106
118
  /**
107
- * Not implemented yet.
108
- * @throws {Error}
119
+ * Replace a child of this node with another node (which is moved if it is already in a tree).
120
+ * @param {PseudoNode} newChild The node which takes the place
121
+ * @param {PseudoNode} oldChild The child of this node to replace
122
+ * @returns {PseudoNode} The replaced node
123
+ * @throws {Error} When the old node is not a child of this node
109
124
  */
110
125
  replaceChild(newChild: PseudoNode, oldChild: PseudoNode): PseudoNode;
111
126
  }