native-document 1.0.8 → 1.0.9
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/package.json +1 -1
- package/src/data/Observable.js +11 -0
- package/src/data/ObservableItem.js +11 -0
- package/src/elements/anchor.js +84 -0
- package/src/elements/control/for-each.js +3 -6
- package/src/elements/control/show-if.js +5 -12
- package/src/elements/control/switch.js +60 -50
- package/src/router/Router.js +20 -1
- package/src/utils/prototypes.js +16 -0
- package/src/wrappers/HtmlElementWrapper.js +24 -1
package/package.json
CHANGED
package/src/data/Observable.js
CHANGED
|
@@ -69,6 +69,10 @@ Observable.init = function(value) {
|
|
|
69
69
|
data[key] = Observable.init(itemValue);
|
|
70
70
|
continue;
|
|
71
71
|
}
|
|
72
|
+
else if(Validator.isArray(itemValue)) {
|
|
73
|
+
data[key] = Observable.array(itemValue);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
72
76
|
data[key] = Observable(itemValue);
|
|
73
77
|
}
|
|
74
78
|
|
|
@@ -86,6 +90,9 @@ Observable.init = function(value) {
|
|
|
86
90
|
}
|
|
87
91
|
return result;
|
|
88
92
|
};
|
|
93
|
+
const $clone = function() {
|
|
94
|
+
|
|
95
|
+
};
|
|
89
96
|
|
|
90
97
|
return new Proxy(data, {
|
|
91
98
|
get(target, property) {
|
|
@@ -95,6 +102,9 @@ Observable.init = function(value) {
|
|
|
95
102
|
if(property === '$val') {
|
|
96
103
|
return $val;
|
|
97
104
|
}
|
|
105
|
+
if(property === '$clone') {
|
|
106
|
+
return $clone;
|
|
107
|
+
}
|
|
98
108
|
if(target[property] !== undefined) {
|
|
99
109
|
return target[property];
|
|
100
110
|
}
|
|
@@ -109,6 +119,7 @@ Observable.init = function(value) {
|
|
|
109
119
|
};
|
|
110
120
|
|
|
111
121
|
Observable.object = Observable.init;
|
|
122
|
+
Observable.json = Observable.init;
|
|
112
123
|
/**
|
|
113
124
|
*
|
|
114
125
|
* @param {Array} target
|
|
@@ -98,4 +98,15 @@ export default function ObservableItem(value) {
|
|
|
98
98
|
return new ObservableChecker(this, callback)
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
+
const $object = this;
|
|
102
|
+
Object.defineProperty($object, '$value', {
|
|
103
|
+
get() {
|
|
104
|
+
return $object.val();
|
|
105
|
+
},
|
|
106
|
+
set(value) {
|
|
107
|
+
$object.set(value);
|
|
108
|
+
return $object;
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
|
|
101
112
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import Validator from "../utils/validator";
|
|
2
|
+
import DebugManager from "../utils/debug-manager";
|
|
3
|
+
import {createTextNode} from "../wrappers/HtmlElementWrapper";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const getChildAsNode = (child) => {
|
|
7
|
+
if(Validator.isFunction(child)) {
|
|
8
|
+
return getChildAsNode(child());
|
|
9
|
+
}
|
|
10
|
+
if(Validator.isElement(child)) {
|
|
11
|
+
return child;
|
|
12
|
+
}
|
|
13
|
+
return createTextNode(String(child))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function Anchor(name) {
|
|
17
|
+
const element = document.createDocumentFragment();
|
|
18
|
+
|
|
19
|
+
const anchorStart = document.createComment('Anchor Start : '+name);
|
|
20
|
+
const anchorEnd = document.createComment('/ Anchor End '+name);
|
|
21
|
+
|
|
22
|
+
element.appendChild(anchorStart);
|
|
23
|
+
element.appendChild(anchorEnd);
|
|
24
|
+
|
|
25
|
+
element.nativeInsertBefore = element.insertBefore;
|
|
26
|
+
element.nativeAppendChild = element.appendChild;
|
|
27
|
+
|
|
28
|
+
const insertBefore = function(parent, child, target) {
|
|
29
|
+
if(parent === element) {
|
|
30
|
+
parent.nativeInsertBefore(getChildAsNode(child), target);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
parent.insertBefore(getChildAsNode(child), target);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
element.appendChild = function(child, before = null) {
|
|
37
|
+
const parent = anchorEnd.parentNode;
|
|
38
|
+
if(!parent) {
|
|
39
|
+
DebugManager.error('Anchor', 'Anchor : parent not found', child);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
before = before ?? anchorEnd;
|
|
43
|
+
if(Validator.isArray(child)) {
|
|
44
|
+
child.forEach((element) => {
|
|
45
|
+
insertBefore(parent, element, before);
|
|
46
|
+
});
|
|
47
|
+
return element;
|
|
48
|
+
}
|
|
49
|
+
insertBefore(parent, child, before);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
element.remove = function(trueRemove) {
|
|
53
|
+
if(anchorEnd.parentNode === element) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let itemToRemove = anchorStart.nextSibling, tempItem;
|
|
57
|
+
while(itemToRemove !== anchorEnd) {
|
|
58
|
+
tempItem = itemToRemove.nextSibling;
|
|
59
|
+
trueRemove ? itemToRemove.remove() : element.nativeAppendChild(itemToRemove);
|
|
60
|
+
itemToRemove = tempItem;
|
|
61
|
+
}
|
|
62
|
+
if(trueRemove) {
|
|
63
|
+
anchorEnd.remove();
|
|
64
|
+
anchorStart.remove();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
element.insertBefore = function(child, anchor = null) {
|
|
69
|
+
element.appendChild(child, anchor);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
element.clear = function() {
|
|
73
|
+
element.remove();
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
element.endElement = function() {
|
|
77
|
+
return anchorEnd;
|
|
78
|
+
};
|
|
79
|
+
element.startElement = function() {
|
|
80
|
+
return anchorStart;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return element;
|
|
84
|
+
};
|
|
@@ -3,6 +3,7 @@ import {Observable} from "../../data/Observable";
|
|
|
3
3
|
import {createTextNode} from "../../wrappers/HtmlElementWrapper";
|
|
4
4
|
import Validator from "../../utils/validator";
|
|
5
5
|
import {throttle} from "../../utils/helpers.js";
|
|
6
|
+
import Anchor from "../anchor";
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -43,12 +44,8 @@ const cleanBlockByCache = (cache, keyIds) => {
|
|
|
43
44
|
* @returns {DocumentFragment}
|
|
44
45
|
*/
|
|
45
46
|
export function ForEach(data, callback, key) {
|
|
46
|
-
const element =
|
|
47
|
-
const
|
|
48
|
-
const blockEnd = document.createComment('Foreach end');
|
|
49
|
-
|
|
50
|
-
element.appendChild(blockStart);
|
|
51
|
-
element.appendChild(blockEnd);
|
|
47
|
+
const element = new Anchor('ForEach');
|
|
48
|
+
const blockEnd = element.endElement();
|
|
52
49
|
|
|
53
50
|
let cache = new Map();
|
|
54
51
|
|
|
@@ -2,6 +2,7 @@ import { Observable } from "../../data/Observable";
|
|
|
2
2
|
import {createTextNode} from "../../wrappers/HtmlElementWrapper";
|
|
3
3
|
import Validator from "../../utils/validator";
|
|
4
4
|
import DebugManager from "../../utils/debug-manager.js";
|
|
5
|
+
import Anchor from "../anchor";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Show the element if the condition is true
|
|
@@ -15,12 +16,7 @@ export const ShowIf = function(condition, child, comment = null) {
|
|
|
15
16
|
if(!(Validator.isObservable(condition))) {
|
|
16
17
|
return DebugManager.warn('ShowIf', "ShowIf : condition must be an Observable / "+comment, condition);
|
|
17
18
|
}
|
|
18
|
-
const element =
|
|
19
|
-
const positionKeeperStart = document.createComment('Show if : '+(comment || ''));
|
|
20
|
-
const positionKeeperEnd = document.createComment('Show if : '+(comment || ''));
|
|
21
|
-
|
|
22
|
-
element.appendChild(positionKeeperStart);
|
|
23
|
-
element.appendChild(positionKeeperEnd);
|
|
19
|
+
const element = new Anchor('Show if : '+(comment || ''));
|
|
24
20
|
|
|
25
21
|
let childElement = null;
|
|
26
22
|
const getChildElement = () => {
|
|
@@ -45,13 +41,10 @@ export const ShowIf = function(condition, child, comment = null) {
|
|
|
45
41
|
element.appendChild(getChildElement());
|
|
46
42
|
}
|
|
47
43
|
condition.subscribe(value => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
parent.insertBefore(getChildElement(), positionKeeperEnd);
|
|
44
|
+
if(value) {
|
|
45
|
+
element.appendChild(getChildElement());
|
|
51
46
|
} else {
|
|
52
|
-
|
|
53
|
-
childElement.remove();
|
|
54
|
-
}
|
|
47
|
+
element.remove();
|
|
55
48
|
}
|
|
56
49
|
});
|
|
57
50
|
|
|
@@ -1,88 +1,98 @@
|
|
|
1
1
|
import NativeDocumentError from "../../errors/NativeDocumentError";
|
|
2
2
|
import {createTextNode} from "../../wrappers/HtmlElementWrapper";
|
|
3
3
|
import Validator from "../../utils/validator";
|
|
4
|
+
import Anchor from "../anchor";
|
|
5
|
+
|
|
6
|
+
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
*
|
|
7
|
-
* @param {ObservableItem|ObservableChecker} condition
|
|
8
|
-
* @param {*}
|
|
9
|
-
* @param {*} onFalse
|
|
10
|
+
* @param {ObservableItem|ObservableChecker} $condition
|
|
11
|
+
* @param {{[key]: *}} values
|
|
10
12
|
* @returns {DocumentFragment}
|
|
11
13
|
*/
|
|
12
|
-
export const
|
|
14
|
+
export const Match = function($condition, values) {
|
|
13
15
|
|
|
14
|
-
if(!Validator.isObservable(condition)) {
|
|
16
|
+
if(!Validator.isObservable($condition)) {
|
|
15
17
|
throw new NativeDocumentError("Toggle : condition must be an Observable");
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
+
const anchor = new Anchor();
|
|
21
|
+
const cache = new Map();
|
|
20
22
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
const getItem = function(key) {
|
|
24
|
+
if(cache.has(key)) {
|
|
25
|
+
return cache.get(key);
|
|
26
|
+
}
|
|
27
|
+
let item = values[key];
|
|
28
|
+
if(!item) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
if(Validator.isFunction(item)) {
|
|
32
|
+
item = item();
|
|
33
|
+
}
|
|
34
|
+
cache.set(key, item);
|
|
35
|
+
return item;
|
|
32
36
|
}
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
|
|
38
|
+
const defaultValue = $condition.val();
|
|
39
|
+
const defaultContent = getItem(defaultValue);
|
|
40
|
+
if(defaultContent) {
|
|
41
|
+
anchor.appendChild(defaultContent);
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
$condition.subscribe(value => {
|
|
45
|
+
const content = getItem(value);
|
|
46
|
+
anchor.remove();
|
|
47
|
+
if(content) {
|
|
48
|
+
anchor.appendChild(content);
|
|
41
49
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
elements.onFalseNode && elements.onFalseNode.remove();
|
|
47
|
-
parent.insertBefore(elements.onTrueNode, commentEnd);
|
|
48
|
-
} else {
|
|
49
|
-
if(!elements.onFalseNode && Validator.isFunction(onFalse)) {
|
|
50
|
-
elements.onFalseNode = onFalse();
|
|
51
|
-
}
|
|
52
|
-
elements.onTrueNode && elements.onTrueNode.remove();
|
|
53
|
-
parent.insertBefore(elements.onFalseNode, commentEnd);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return anchor;
|
|
53
|
+
}
|
|
56
54
|
|
|
57
|
-
condition.subscribe(handle);
|
|
58
|
-
handle(condition.val());
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {ObservableItem|ObservableChecker} $condition
|
|
59
|
+
* @param {*} onTrue
|
|
60
|
+
* @param {*} onFalse
|
|
61
|
+
* @returns {DocumentFragment}
|
|
62
|
+
*/
|
|
63
|
+
export const Switch = function ($condition, onTrue, onFalse) {
|
|
64
|
+
|
|
65
|
+
if(!Validator.isObservable($condition)) {
|
|
66
|
+
throw new NativeDocumentError("Toggle : condition must be an Observable");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return Match($condition, {
|
|
70
|
+
true: onTrue,
|
|
71
|
+
false: onFalse,
|
|
72
|
+
});
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
/**
|
|
64
76
|
*
|
|
65
|
-
* @param condition
|
|
77
|
+
* @param {ObservableItem|ObservableChecker} $condition
|
|
66
78
|
* @returns {{show: Function, otherwise: (((*) => {}):DocumentFragment)}
|
|
67
79
|
*/
|
|
68
|
-
export const When = function(condition) {
|
|
80
|
+
export const When = function($condition) {
|
|
81
|
+
if(!Validator.isObservable($condition)) {
|
|
82
|
+
throw new NativeDocumentError("When : condition must be an Observable");
|
|
83
|
+
}
|
|
84
|
+
|
|
69
85
|
let $onTrue = null;
|
|
70
86
|
let $onFalse = null;
|
|
71
87
|
|
|
72
88
|
return {
|
|
73
89
|
show(onTrue) {
|
|
74
|
-
if(!Validator.isElement(onTrue) && !Validator.isFunction(onTrue)) {
|
|
75
|
-
throw new NativeDocumentError("When : onTrue must be a valid Element");
|
|
76
|
-
}
|
|
77
90
|
$onTrue = onTrue;
|
|
78
91
|
return this;
|
|
79
92
|
},
|
|
80
93
|
otherwise(onFalse) {
|
|
81
|
-
if(!Validator.isElement(onFalse) && !Validator.isFunction(onFalse)) {
|
|
82
|
-
throw new NativeDocumentError("When : onFalse must be a valid Element");
|
|
83
|
-
}
|
|
84
94
|
$onFalse = onFalse;
|
|
85
|
-
return Switch(condition, $onTrue, $onFalse);
|
|
95
|
+
return Switch($condition, $onTrue, $onFalse);
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
98
|
}
|
package/src/router/Router.js
CHANGED
|
@@ -227,5 +227,24 @@ Router.create = function(options, callback) {
|
|
|
227
227
|
};
|
|
228
228
|
|
|
229
229
|
Router.get = function(name) {
|
|
230
|
-
|
|
230
|
+
const router = Router.routers[name || DEFAULT_ROUTER_NAME];
|
|
231
|
+
if(!router) {
|
|
232
|
+
throw new RouterError(`Router not found for name: ${name}`);
|
|
233
|
+
}
|
|
234
|
+
return router;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
Router.push = function(target, name = null) {
|
|
238
|
+
return Router.get(name).push(target);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
Router.replace = function(target, name = null) {
|
|
242
|
+
return Router.get(name).replace(target);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
Router.forward = function(name = null) {
|
|
246
|
+
return Router.get(name).forward();
|
|
247
|
+
};
|
|
248
|
+
Router.back = function(name = null) {
|
|
249
|
+
return Router.get(name).back();
|
|
231
250
|
};
|
package/src/utils/prototypes.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {withValidation} from "./args-types.js";
|
|
2
|
+
import {Observable} from "../data/Observable";
|
|
3
|
+
import Validator from "./validator";
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
Function.prototype.args = function(...args) {
|
|
@@ -13,4 +15,18 @@ Function.prototype.errorBoundary = function(callback) {
|
|
|
13
15
|
return callback(e);
|
|
14
16
|
}
|
|
15
17
|
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
String.prototype.use = function(args) {
|
|
21
|
+
const value = this;
|
|
22
|
+
|
|
23
|
+
return Observable.computed(() => {
|
|
24
|
+
return value.replace(/\$\{(.*?)}/g, (match, key) => {
|
|
25
|
+
const data = args[key];
|
|
26
|
+
if(Validator.isObservable(data)) {
|
|
27
|
+
return data.val();
|
|
28
|
+
}
|
|
29
|
+
return data;
|
|
30
|
+
});
|
|
31
|
+
}, Object.values(args));
|
|
16
32
|
}
|
|
@@ -4,6 +4,7 @@ import NativeDocumentError from "../errors/NativeDocumentError";
|
|
|
4
4
|
import DocumentObserver from "./DocumentObserver";
|
|
5
5
|
import Validator from "../utils/validator";
|
|
6
6
|
import DebugManager from "../utils/debug-manager";
|
|
7
|
+
import Anchor from "../elements/anchor";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
@@ -51,6 +52,20 @@ const addUtilsMethods = function(element) {
|
|
|
51
52
|
|
|
52
53
|
let $observer = null;
|
|
53
54
|
|
|
55
|
+
element.nd.appendChild = function(child) {
|
|
56
|
+
if(Validator.isArray(child)) {
|
|
57
|
+
ElementCreator.processChildren(child, element);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if(Validator.isFunction(child)) {
|
|
61
|
+
child = child();
|
|
62
|
+
ElementCreator.processChildren(child(), element);
|
|
63
|
+
}
|
|
64
|
+
if(Validator.isElement(child)) {
|
|
65
|
+
ElementCreator.processChildren(child, element);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
54
69
|
element.nd.lifecycle = function(states) {
|
|
55
70
|
$observer = $observer || DocumentObserver.watch(element);
|
|
56
71
|
|
|
@@ -89,7 +104,7 @@ export const ElementCreator = {
|
|
|
89
104
|
* @returns {HTMLElement|DocumentFragment}
|
|
90
105
|
*/
|
|
91
106
|
createElement(name) {
|
|
92
|
-
return name ? document.createElement(name) :
|
|
107
|
+
return name ? document.createElement(name) : new Anchor('Fragment');
|
|
93
108
|
},
|
|
94
109
|
/**
|
|
95
110
|
*
|
|
@@ -101,6 +116,14 @@ export const ElementCreator = {
|
|
|
101
116
|
const childrenArray = Array.isArray(children) ? children : [children];
|
|
102
117
|
childrenArray.forEach(child => {
|
|
103
118
|
if (child === null) return;
|
|
119
|
+
if(Validator.isFunction(child)) {
|
|
120
|
+
this.processChildren(child(), parent);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if(Validator.isArray(child)) {
|
|
124
|
+
this.processChildren(child, parent);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
104
127
|
if (Validator.isElement(child)) {
|
|
105
128
|
parent.appendChild(child);
|
|
106
129
|
return;
|