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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-document",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -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 = document.createDocumentFragment();
47
- const blockStart = document.createComment('Foreach start');
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 = document.createDocumentFragment();
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
- const parent = positionKeeperEnd.parentNode;
49
- if(value && parent) {
50
- parent.insertBefore(getChildElement(), positionKeeperEnd);
44
+ if(value) {
45
+ element.appendChild(getChildElement());
51
46
  } else {
52
- if(Validator.isElement(childElement)){
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 {*} onTrue
9
- * @param {*} onFalse
10
+ * @param {ObservableItem|ObservableChecker} $condition
11
+ * @param {{[key]: *}} values
10
12
  * @returns {DocumentFragment}
11
13
  */
12
- export const Switch = function (condition, onTrue, onFalse) {
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 commentStart = document.createComment('Toggle Start');
19
- const commentEnd = document.createComment('Toggle End');
20
+ const anchor = new Anchor();
21
+ const cache = new Map();
20
22
 
21
- const element = document.createDocumentFragment();
22
- element.appendChild(commentStart);
23
- element.appendChild(commentEnd);
24
-
25
- const elements = {
26
- onTrueNode: (Validator.isFunction(onTrue)) ? null : onTrue,
27
- onFalseNode: (Validator.isFunction(onFalse)) ? null : onFalse,
28
- };
29
-
30
- if(Validator.isStringOrObservable(elements.onTrueNode)) {
31
- elements.onTrueNode = createTextNode(elements.onTrueNode);
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
- if(Validator.isStringOrObservable(elements.onFalseNode)) {
34
- elements.onFalseNode = createTextNode(elements.onFalseNode);
37
+
38
+ const defaultValue = $condition.val();
39
+ const defaultContent = getItem(defaultValue);
40
+ if(defaultContent) {
41
+ anchor.appendChild(defaultContent);
35
42
  }
36
43
 
37
- const handle = (value) => {
38
- const parent = commentEnd.parentNode;
39
- if(!parent) {
40
- return;
44
+ $condition.subscribe(value => {
45
+ const content = getItem(value);
46
+ anchor.remove();
47
+ if(content) {
48
+ anchor.appendChild(content);
41
49
  }
42
- if(value) {
43
- if(!elements.onTrueNode && Validator.isFunction(onTrue)) {
44
- elements.onTrueNode = onTrue();
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
- return element;
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
  }
@@ -227,5 +227,24 @@ Router.create = function(options, callback) {
227
227
  };
228
228
 
229
229
  Router.get = function(name) {
230
- return Router.routers[name || DEFAULT_ROUTER_NAME];
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
  };
@@ -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) : document.createDocumentFragment();
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;