native-document 1.0.14 → 1.0.16
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.
- package/dist/native-document.dev.js +1262 -842
- package/dist/native-document.min.js +1 -1
- package/docs/anchor.md +216 -53
- package/docs/conditional-rendering.md +25 -24
- package/docs/core-concepts.md +20 -19
- package/docs/elements.md +21 -20
- package/docs/getting-started.md +28 -27
- package/docs/lifecycle-events.md +2 -2
- package/docs/list-rendering.md +607 -0
- package/docs/memory-management.md +1 -1
- package/docs/observables.md +15 -14
- package/docs/routing.md +22 -22
- package/docs/state-management.md +8 -8
- package/docs/validation.md +0 -2
- package/index.js +6 -1
- package/package.json +1 -1
- package/readme.md +5 -4
- package/src/data/MemoryManager.js +8 -20
- package/src/data/Observable.js +2 -180
- package/src/data/ObservableChecker.js +25 -24
- package/src/data/ObservableItem.js +158 -79
- package/src/data/observable-helpers/array.js +74 -0
- package/src/data/observable-helpers/batch.js +22 -0
- package/src/data/observable-helpers/computed.js +28 -0
- package/src/data/observable-helpers/object.js +111 -0
- package/src/elements/anchor.js +54 -9
- package/src/elements/control/for-each-array.js +280 -0
- package/src/elements/control/for-each.js +87 -110
- package/src/elements/form.js +1 -1
- package/src/elements/index.js +1 -0
- package/src/elements/list.js +4 -0
- package/src/router/link.js +2 -2
- package/src/utils/helpers.js +44 -21
- package/src/wrappers/AttributesWrapper.js +5 -18
- package/src/wrappers/DocumentObserver.js +58 -29
- package/src/wrappers/ElementCreator.js +114 -0
- package/src/wrappers/HtmlElementEventsWrapper.js +52 -65
- package/src/wrappers/HtmlElementWrapper.js +11 -167
- package/src/wrappers/NdPrototype.js +106 -0
|
@@ -3,20 +3,6 @@ import NativeDocumentError from "../errors/NativeDocumentError";
|
|
|
3
3
|
import {BOOLEAN_ATTRIBUTES} from "./constants.js";
|
|
4
4
|
import {Observable} from "../data/Observable";
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
* @param {HTMLElement} element
|
|
9
|
-
* @param {string} className
|
|
10
|
-
* @param {string} value
|
|
11
|
-
*/
|
|
12
|
-
const toggleClassItem = function(element, className, value) {
|
|
13
|
-
if(value) {
|
|
14
|
-
element.classList.add(className);
|
|
15
|
-
} else {
|
|
16
|
-
element.classList.remove(className);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
6
|
/**
|
|
21
7
|
*
|
|
22
8
|
* @param {HTMLElement} element
|
|
@@ -26,11 +12,11 @@ function bindClassAttribute(element, data) {
|
|
|
26
12
|
for(let className in data) {
|
|
27
13
|
const value = data[className];
|
|
28
14
|
if(Validator.isObservable(value)) {
|
|
29
|
-
|
|
30
|
-
value.subscribe(newValue =>
|
|
15
|
+
element.classList.toggle(className, value.val());
|
|
16
|
+
value.subscribe(newValue => element.classList.toggle(className, newValue));
|
|
31
17
|
continue;
|
|
32
18
|
}
|
|
33
|
-
|
|
19
|
+
element.classList.toggle(className, value)
|
|
34
20
|
}
|
|
35
21
|
}
|
|
36
22
|
|
|
@@ -102,8 +88,8 @@ function bindAttributeWithObservable(element, attributeName, value) {
|
|
|
102
88
|
}
|
|
103
89
|
element.setAttribute(attributeName, newValue);
|
|
104
90
|
};
|
|
91
|
+
applyValue(value.val());
|
|
105
92
|
value.subscribe(applyValue);
|
|
106
|
-
applyValue(value.val())
|
|
107
93
|
|
|
108
94
|
if(attributeName === 'value') {
|
|
109
95
|
element.addEventListener('input', () => value.set(element.value));
|
|
@@ -152,6 +138,7 @@ export default function AttributesWrapper(element, attributes) {
|
|
|
152
138
|
continue;
|
|
153
139
|
}
|
|
154
140
|
element.setAttribute(attributeName, value);
|
|
141
|
+
|
|
155
142
|
}
|
|
156
143
|
return element;
|
|
157
144
|
}
|
|
@@ -1,44 +1,73 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {debounce} from "../utils/helpers";
|
|
2
2
|
|
|
3
3
|
const DocumentObserver = {
|
|
4
|
-
|
|
4
|
+
mounted: new WeakMap(),
|
|
5
|
+
mountedSupposedSize: 0,
|
|
6
|
+
unmounted: new WeakMap(),
|
|
7
|
+
unmountedSupposedSize: 0,
|
|
5
8
|
observer: null,
|
|
6
|
-
checkMutation:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
checkMutation: debounce(function(mutationsList) {
|
|
10
|
+
let i = 0;
|
|
11
|
+
for(const mutation of mutationsList) {
|
|
12
|
+
if(DocumentObserver.mountedSupposedSize > 0 ) {
|
|
13
|
+
for(const node of mutation.addedNodes) {
|
|
14
|
+
const data = DocumentObserver.mounted.get(node);
|
|
15
|
+
if(!data) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
data.inDom = true;
|
|
19
|
+
data.mounted && data.mounted(node);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if(DocumentObserver.unmountedSupposedSize > 0 ) {
|
|
24
|
+
for(const node of mutation.removedNodes) {
|
|
25
|
+
const data = DocumentObserver.unmounted.get(node);
|
|
26
|
+
if(!data) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
data.inDom = false;
|
|
31
|
+
if(data.unmounted && data.unmounted(node) === true) {
|
|
32
|
+
data.disconnect();
|
|
33
|
+
node.nd?.remove();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
15
36
|
}
|
|
16
37
|
}
|
|
17
|
-
},
|
|
38
|
+
}, 16),
|
|
18
39
|
/**
|
|
19
40
|
*
|
|
20
41
|
* @param {HTMLElement} element
|
|
42
|
+
* @param {boolean} inDom
|
|
21
43
|
* @returns {{watch: (function(): Map<any, any>), disconnect: (function(): boolean), mounted: (function(*): Set<any>), unmounted: (function(*): Set<any>)}}
|
|
22
44
|
*/
|
|
23
|
-
watch: function(element) {
|
|
24
|
-
let data = {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
45
|
+
watch: function(element, inDom = false) {
|
|
46
|
+
let data = {
|
|
47
|
+
inDom,
|
|
48
|
+
mounted: null,
|
|
49
|
+
unmounted: null,
|
|
50
|
+
disconnect: () => {
|
|
51
|
+
DocumentObserver.mounted.delete(element);
|
|
52
|
+
DocumentObserver.unmounted.delete(element);
|
|
53
|
+
DocumentObserver.mountedSupposedSize--;
|
|
54
|
+
DocumentObserver.unmountedSupposedSize--;
|
|
55
|
+
data = null;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
36
58
|
|
|
37
59
|
return {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
60
|
+
disconnect: data.disconnect,
|
|
61
|
+
mounted: (callback) => {
|
|
62
|
+
data.mounted = callback;
|
|
63
|
+
DocumentObserver.mounted.set(element, data);
|
|
64
|
+
DocumentObserver.mountedSupposedSize++;
|
|
65
|
+
},
|
|
66
|
+
unmounted: (callback) => {
|
|
67
|
+
data.unmounted = callback;
|
|
68
|
+
DocumentObserver.unmounted.set(element, data);
|
|
69
|
+
DocumentObserver.unmountedSupposedSize++;
|
|
70
|
+
}
|
|
42
71
|
};
|
|
43
72
|
}
|
|
44
73
|
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import Anchor from "../elements/anchor";
|
|
2
|
+
import Validator from "../utils/validator";
|
|
3
|
+
import AttributesWrapper from "./AttributesWrapper";
|
|
4
|
+
|
|
5
|
+
const $nodeCache = new Map();
|
|
6
|
+
let $textNodeCache = null;
|
|
7
|
+
|
|
8
|
+
export const ElementCreator = {
|
|
9
|
+
createTextNode() {
|
|
10
|
+
if(!$textNodeCache) {
|
|
11
|
+
$textNodeCache = document.createTextNode('');
|
|
12
|
+
}
|
|
13
|
+
return $textNodeCache.cloneNode();
|
|
14
|
+
},
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {HTMLElement|DocumentFragment} parent
|
|
18
|
+
* @param {ObservableItem} observable
|
|
19
|
+
* @returns {Text}
|
|
20
|
+
*/
|
|
21
|
+
createObservableNode(parent, observable) {
|
|
22
|
+
const text = ElementCreator.createTextNode();
|
|
23
|
+
observable.subscribe(value => text.nodeValue = String(value));
|
|
24
|
+
text.nodeValue = observable.val();
|
|
25
|
+
parent && parent.appendChild(text);
|
|
26
|
+
return text;
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param {HTMLElement|DocumentFragment} parent
|
|
32
|
+
* @param {*} value
|
|
33
|
+
* @returns {Text}
|
|
34
|
+
*/
|
|
35
|
+
createStaticTextNode(parent, value) {
|
|
36
|
+
let text = ElementCreator.createTextNode();
|
|
37
|
+
text.nodeValue = String(value);
|
|
38
|
+
parent && parent.appendChild(text);
|
|
39
|
+
return text;
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @param {string} name
|
|
44
|
+
* @returns {HTMLElement|DocumentFragment}
|
|
45
|
+
*/
|
|
46
|
+
createElement(name) {
|
|
47
|
+
if(name) {
|
|
48
|
+
if($nodeCache.has(name)) {
|
|
49
|
+
return $nodeCache.get(name).cloneNode();
|
|
50
|
+
}
|
|
51
|
+
const node = document.createElement(name);
|
|
52
|
+
$nodeCache.set(name, node);
|
|
53
|
+
return node.cloneNode();
|
|
54
|
+
}
|
|
55
|
+
return new Anchor('Fragment');
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @param {*} children
|
|
60
|
+
* @param {HTMLElement|DocumentFragment} parent
|
|
61
|
+
*/
|
|
62
|
+
processChildren(children, parent) {
|
|
63
|
+
if(children === null) return;
|
|
64
|
+
const childrenArray = Array.isArray(children) ? children : [children];
|
|
65
|
+
|
|
66
|
+
for(let i = 0, length = childrenArray.length; i < length; i++) {
|
|
67
|
+
let child = childrenArray[i];
|
|
68
|
+
if (child === null) continue;
|
|
69
|
+
if(Validator.isString(child) && Validator.isFunction(child.resolveObservableTemplate)) {
|
|
70
|
+
child = child.resolveObservableTemplate();
|
|
71
|
+
}
|
|
72
|
+
if(Validator.isFunction(child)) {
|
|
73
|
+
this.processChildren(child(), parent);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if(Validator.isArray(child)) {
|
|
77
|
+
this.processChildren(child, parent);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (Validator.isElement(child)) {
|
|
81
|
+
parent.appendChild(child);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (Validator.isObservable(child)) {
|
|
85
|
+
ElementCreator.createObservableNode(parent, child);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (child) {
|
|
89
|
+
ElementCreator.createStaticTextNode(parent, child);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @param {HTMLElement} element
|
|
96
|
+
* @param {Object} attributes
|
|
97
|
+
*/
|
|
98
|
+
processAttributes(element, attributes) {
|
|
99
|
+
if(Validator.isFragment(element)) return;
|
|
100
|
+
if (attributes) {
|
|
101
|
+
AttributesWrapper(element, attributes);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
/**
|
|
105
|
+
*
|
|
106
|
+
* @param {HTMLElement} element
|
|
107
|
+
* @param {Object} attributes
|
|
108
|
+
* @param {?Function} customWrapper
|
|
109
|
+
* @returns {HTMLElement|DocumentFragment}
|
|
110
|
+
*/
|
|
111
|
+
setup(element, attributes, customWrapper) {
|
|
112
|
+
return element;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
@@ -1,6 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {HTMLElement} element
|
|
6
|
+
* @returns {HTMLElement}
|
|
7
|
+
*/
|
|
8
|
+
function HtmlElementPreventEventsWrapper(element) {
|
|
9
|
+
const events = {};
|
|
10
|
+
return new Proxy(events, {
|
|
11
|
+
get(target, property) {
|
|
12
|
+
if(events[property]) {
|
|
13
|
+
return events[property];
|
|
14
|
+
}
|
|
15
|
+
events[property] = function(callback) {
|
|
16
|
+
element.addEventListener(property.toLowerCase(), function(event) {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
callback.apply(this, [event]);
|
|
19
|
+
});
|
|
20
|
+
return element
|
|
21
|
+
};
|
|
22
|
+
return events[property];
|
|
23
|
+
},
|
|
24
|
+
set(target, property, newValue, receiver) {
|
|
25
|
+
//...
|
|
26
|
+
this.get(target, property)(newValue);
|
|
27
|
+
return element;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
4
30
|
}
|
|
5
31
|
|
|
6
32
|
/**
|
|
@@ -9,69 +35,30 @@ function eventWrapper(element, name, callback) {
|
|
|
9
35
|
* @returns {HTMLElement}
|
|
10
36
|
*/
|
|
11
37
|
export default function HtmlElementEventsWrapper(element) {
|
|
38
|
+
const events = {};
|
|
39
|
+
return new Proxy(events, {
|
|
40
|
+
get(target, property) {
|
|
41
|
+
if(events[property]) {
|
|
42
|
+
return events[property];
|
|
43
|
+
}
|
|
44
|
+
if(property === 'prevent') {
|
|
45
|
+
events[property] = HtmlElementPreventEventsWrapper(element);
|
|
46
|
+
return events[property];
|
|
47
|
+
}
|
|
48
|
+
if(property === 'removeAll') {
|
|
12
49
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
element.nd.on = function(events) {
|
|
21
|
-
for(const event in events) {
|
|
22
|
-
const callback = events[event];
|
|
23
|
-
eventWrapper(element, event, callback);
|
|
24
|
-
}
|
|
25
|
-
return element;
|
|
26
|
-
};
|
|
27
|
-
element.nd.on.prevent = function(events) {
|
|
28
|
-
for(const event in events) {
|
|
29
|
-
const callback = events[event];
|
|
30
|
-
eventWrapper(element, event, (event) => {
|
|
31
|
-
event.preventDefault();
|
|
32
|
-
callback && callback(event);
|
|
33
|
-
return element;
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
return element;
|
|
37
|
-
};
|
|
38
|
-
const events = {
|
|
39
|
-
click: (callback) => eventWrapper(element, 'click', callback),
|
|
40
|
-
focus: (callback) => eventWrapper(element, 'focus', callback),
|
|
41
|
-
blur: (callback) => eventWrapper(element, 'blur', callback),
|
|
42
|
-
input: (callback) => eventWrapper(element, 'input', callback),
|
|
43
|
-
change: (callback) => eventWrapper(element, 'change', callback),
|
|
44
|
-
keyup: (callback) => eventWrapper(element, 'keyup', callback),
|
|
45
|
-
keydown: (callback) => eventWrapper(element, 'keydown', callback),
|
|
46
|
-
beforeInput: (callback) => eventWrapper(element, 'beforeinput', callback),
|
|
47
|
-
mouseOver: (callback) => eventWrapper(element, 'mouseover', callback),
|
|
48
|
-
mouseOut: (callback) => eventWrapper(element, 'mouseout', callback),
|
|
49
|
-
mouseDown: (callback) => eventWrapper(element, 'mousedown', callback),
|
|
50
|
-
mouseUp: (callback) => eventWrapper(element, 'mouseup', callback),
|
|
51
|
-
mouseMove: (callback) => eventWrapper(element, 'mousemove', callback),
|
|
52
|
-
hover: (mouseInCallback, mouseOutCallback) => {
|
|
53
|
-
element.addEventListener('mouseover', mouseInCallback);
|
|
54
|
-
element.addEventListener('mouseout', mouseOutCallback);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
events[property] = function(callback) {
|
|
53
|
+
element.addEventListener(property.toLowerCase(), callback);
|
|
54
|
+
return element
|
|
55
|
+
};
|
|
56
|
+
return events[property];
|
|
55
57
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
dragStart: (callback) => eventWrapper(element, 'dragstart', callback),
|
|
60
|
-
drop: (callback) => eventWrapper(element, 'drop', callback),
|
|
61
|
-
dragOver: (callback) => eventWrapper(element, 'dragover', callback),
|
|
62
|
-
dragEnter: (callback) => eventWrapper(element, 'dragenter', callback),
|
|
63
|
-
dragLeave: (callback) => eventWrapper(element, 'dragleave', callback),
|
|
64
|
-
};
|
|
65
|
-
for(let event in events) {
|
|
66
|
-
element.nd.on[event] = events[event];
|
|
67
|
-
element.nd.on.prevent[event] = function(callback) {
|
|
68
|
-
eventWrapper(element, event.toLowerCase(), (event) => {
|
|
69
|
-
event.preventDefault();
|
|
70
|
-
callback && callback(event);
|
|
71
|
-
});
|
|
58
|
+
set(target, property, newValue, receiver) {
|
|
59
|
+
//...
|
|
60
|
+
this.get(target, property)(newValue);
|
|
72
61
|
return element;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return element;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
77
64
|
}
|
|
@@ -1,91 +1,7 @@
|
|
|
1
|
-
import HtmlElementEventsWrapper from "./HtmlElementEventsWrapper";
|
|
2
|
-
import AttributesWrapper from "./AttributesWrapper";
|
|
3
|
-
import NativeDocumentError from "../errors/NativeDocumentError";
|
|
4
|
-
import DocumentObserver from "./DocumentObserver";
|
|
5
1
|
import Validator from "../utils/validator";
|
|
6
2
|
import DebugManager from "../utils/debug-manager";
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* @param {HTMLElement|DocumentFragment} parent
|
|
13
|
-
* @param {ObservableItem} observable
|
|
14
|
-
* @returns {Text}
|
|
15
|
-
*/
|
|
16
|
-
const createObservableNode = function(parent, observable) {
|
|
17
|
-
const text = document.createTextNode('');
|
|
18
|
-
observable.subscribe(value => text.textContent = String(value));
|
|
19
|
-
text.textContent = observable.val();
|
|
20
|
-
parent && parent.appendChild(text);
|
|
21
|
-
return text;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* @param {HTMLElement|DocumentFragment} parent
|
|
27
|
-
* @param {*} value
|
|
28
|
-
* @returns {Text}
|
|
29
|
-
*/
|
|
30
|
-
const createStaticTextNode = function(parent, value) {
|
|
31
|
-
const text = document.createTextNode('');
|
|
32
|
-
text.textContent = String(value);
|
|
33
|
-
parent && parent.appendChild(text);
|
|
34
|
-
return text;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* @param {HTMLElement} element
|
|
40
|
-
*/
|
|
41
|
-
const addUtilsMethods = function(element) {
|
|
42
|
-
element.nd.wrap = (callback) => {
|
|
43
|
-
if(!Validator.isFunction(callback)) {
|
|
44
|
-
throw new NativeDocumentError('Callback must be a function');
|
|
45
|
-
}
|
|
46
|
-
callback && callback(element);
|
|
47
|
-
return element;
|
|
48
|
-
};
|
|
49
|
-
element.nd.ref = (target, name) => {
|
|
50
|
-
target[name] = element;
|
|
51
|
-
return element;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
let $observer = null;
|
|
55
|
-
|
|
56
|
-
element.nd.appendChild = function(child) {
|
|
57
|
-
if(Validator.isArray(child)) {
|
|
58
|
-
ElementCreator.processChildren(child, element);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if(Validator.isFunction(child)) {
|
|
62
|
-
child = child();
|
|
63
|
-
ElementCreator.processChildren(child(), element);
|
|
64
|
-
}
|
|
65
|
-
if(Validator.isElement(child)) {
|
|
66
|
-
ElementCreator.processChildren(child, element);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
element.nd.lifecycle = function(states) {
|
|
71
|
-
$observer = $observer || DocumentObserver.watch(element);
|
|
72
|
-
|
|
73
|
-
states.mounted && $observer.mounted(states.mounted);
|
|
74
|
-
states.unmounted && $observer.unmounted(states.unmounted);
|
|
75
|
-
return element;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
element.nd.mounted = (callback) => {
|
|
79
|
-
$observer = $observer || DocumentObserver.watch(element);
|
|
80
|
-
$observer.mounted(callback);
|
|
81
|
-
return element;
|
|
82
|
-
};
|
|
83
|
-
element.nd.unmounted = (callback) => {
|
|
84
|
-
$observer = $observer || DocumentObserver.watch(element);
|
|
85
|
-
$observer.unmounted(callback);
|
|
86
|
-
return element;
|
|
87
|
-
};
|
|
88
|
-
};
|
|
3
|
+
import {ElementCreator} from "./ElementCreator";
|
|
4
|
+
import './NdPrototype';
|
|
89
5
|
|
|
90
6
|
/**
|
|
91
7
|
*
|
|
@@ -94,84 +10,10 @@ const addUtilsMethods = function(element) {
|
|
|
94
10
|
*/
|
|
95
11
|
export const createTextNode = function(value) {
|
|
96
12
|
return (Validator.isObservable(value))
|
|
97
|
-
? createObservableNode(null, value)
|
|
98
|
-
: createStaticTextNode(null, value);
|
|
13
|
+
? ElementCreator.createObservableNode(null, value)
|
|
14
|
+
: ElementCreator.createStaticTextNode(null, value);
|
|
99
15
|
};
|
|
100
16
|
|
|
101
|
-
export const ElementCreator = {
|
|
102
|
-
/**
|
|
103
|
-
*
|
|
104
|
-
* @param {string} name
|
|
105
|
-
* @returns {HTMLElement|DocumentFragment}
|
|
106
|
-
*/
|
|
107
|
-
createElement(name) {
|
|
108
|
-
return name ? document.createElement(name) : new Anchor('Fragment');
|
|
109
|
-
},
|
|
110
|
-
/**
|
|
111
|
-
*
|
|
112
|
-
* @param {*} children
|
|
113
|
-
* @param {HTMLElement|DocumentFragment} parent
|
|
114
|
-
*/
|
|
115
|
-
processChildren(children, parent) {
|
|
116
|
-
if(children === null) return;
|
|
117
|
-
const childrenArray = Array.isArray(children) ? children : [children];
|
|
118
|
-
childrenArray.forEach(child => {
|
|
119
|
-
if (child === null) return;
|
|
120
|
-
if(Validator.isString(child) && Validator.isFunction(child.resolveObservableTemplate)) {
|
|
121
|
-
child = child.resolveObservableTemplate();
|
|
122
|
-
}
|
|
123
|
-
if(Validator.isFunction(child)) {
|
|
124
|
-
this.processChildren(child(), parent);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if(Validator.isArray(child)) {
|
|
128
|
-
this.processChildren(child, parent);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
if (Validator.isElement(child)) {
|
|
132
|
-
parent.appendChild(child);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
if (Validator.isObservable(child)) {
|
|
136
|
-
createObservableNode(parent, child);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (child) {
|
|
140
|
-
createStaticTextNode(parent, child);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
},
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
* @param {HTMLElement} element
|
|
147
|
-
* @param {Object} attributes
|
|
148
|
-
*/
|
|
149
|
-
processAttributes(element, attributes) {
|
|
150
|
-
if(Validator.isFragment(element)) return;
|
|
151
|
-
if (attributes) {
|
|
152
|
-
AttributesWrapper(element, attributes);
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
/**
|
|
156
|
-
*
|
|
157
|
-
* @param {HTMLElement} element
|
|
158
|
-
* @param {Object} attributes
|
|
159
|
-
* @param {?Function} customWrapper
|
|
160
|
-
* @returns {HTMLElement|DocumentFragment}
|
|
161
|
-
*/
|
|
162
|
-
setup(element, attributes, customWrapper) {
|
|
163
|
-
element.nd = {};
|
|
164
|
-
HtmlElementEventsWrapper(element);
|
|
165
|
-
const item = (typeof customWrapper === 'function') ? customWrapper(element) : element;
|
|
166
|
-
addUtilsMethods(item);
|
|
167
|
-
|
|
168
|
-
PluginsManager.list().forEach(plugin => {
|
|
169
|
-
plugin?.element?.setup && plugin.element.setup(item, attributes);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
return item;
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
17
|
|
|
176
18
|
/**
|
|
177
19
|
*
|
|
@@ -180,7 +22,7 @@ export const ElementCreator = {
|
|
|
180
22
|
* @returns {Function}
|
|
181
23
|
*/
|
|
182
24
|
export default function HtmlElementWrapper(name, customWrapper) {
|
|
183
|
-
const $tagName = name.toLowerCase()
|
|
25
|
+
const $tagName = name.toLowerCase();
|
|
184
26
|
|
|
185
27
|
const builder = function(attributes, children = null) {
|
|
186
28
|
try {
|
|
@@ -190,11 +32,12 @@ export default function HtmlElementWrapper(name, customWrapper) {
|
|
|
190
32
|
attributes = tempChildren;
|
|
191
33
|
}
|
|
192
34
|
const element = ElementCreator.createElement($tagName);
|
|
35
|
+
const finalElement = (typeof customWrapper === 'function') ? customWrapper(element) : element;
|
|
193
36
|
|
|
194
|
-
ElementCreator.processAttributes(
|
|
195
|
-
ElementCreator.processChildren(children,
|
|
37
|
+
ElementCreator.processAttributes(finalElement, attributes);
|
|
38
|
+
ElementCreator.processChildren(children, finalElement);
|
|
196
39
|
|
|
197
|
-
return ElementCreator.setup(
|
|
40
|
+
return ElementCreator.setup(finalElement, attributes, customWrapper);
|
|
198
41
|
} catch (error) {
|
|
199
42
|
DebugManager.error('ElementCreation', `Error creating ${$tagName}`, error);
|
|
200
43
|
}
|
|
@@ -203,4 +46,5 @@ export default function HtmlElementWrapper(name, customWrapper) {
|
|
|
203
46
|
builder.hold = (children, attributes) => (() => builder(children, attributes));
|
|
204
47
|
|
|
205
48
|
return builder;
|
|
206
|
-
}
|
|
49
|
+
}
|
|
50
|
+
|