native-document 1.0.87 → 1.0.89

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.
@@ -6,8 +6,8 @@ export const ObservableWhen = function(observer, value) {
6
6
 
7
7
  ObservableWhen.prototype.__$isObservableWhen = true;
8
8
 
9
- ObservableWhen.prototype.subscribe = function(callback) {
10
- return this.$observer.on(this.$target, callback);
9
+ ObservableWhen.prototype.subscribe = function(callback, context = null) {
10
+ return this.$observer.on(this.$target, callback, context);
11
11
  };
12
12
 
13
13
  ObservableWhen.prototype.val = function() {
@@ -0,0 +1,21 @@
1
+
2
+
3
+ export function CallbackHandler(callback) {
4
+
5
+ if(!(this instanceof CallbackHandler)) {
6
+ return new CallbackHandler(callback);
7
+ }
8
+
9
+ const $contextSore = new WeakMap();
10
+
11
+ this.set = (target, context) => {
12
+ $contextSore.set(target, context);
13
+ };
14
+
15
+ this.callback = function() {
16
+ const context = $contextSore.get(this);
17
+ if(context) {
18
+ callback(context, ...arguments);
19
+ }
20
+ };
21
+ }
@@ -1,50 +1,30 @@
1
1
  import Validator from "../utils/validator";
2
- import NativeDocumentError from "../errors/NativeDocumentError";
3
2
  import {BOOLEAN_ATTRIBUTES} from "./constants.js";
4
3
  import {Observable} from "../data/Observable";
5
- import './prototypes/bind-class-extensions';
6
-
7
-
8
- export function toggleElementClass(element, className, shouldAdd) {
9
- element.classes.toggle(className, shouldAdd);
10
- }
11
-
12
- export function toggleElementStyle(element, styleName, newValue) {
13
- element.style[styleName] = newValue;
14
- }
15
-
16
- export function updateInputFromObserver(element, attributeName, newValue) {
17
- if(Validator.isBoolean(newValue)) {
18
- element[attributeName] = newValue;
19
- return;
20
- }
21
- element[attributeName] = newValue === element.value;
22
- }
23
-
24
- export function updateObserverFromInput(element, attributeName, defaultValue, value) {
25
- if(Validator.isBoolean(defaultValue)) {
26
- value.set(element[attributeName]);
27
- return;
28
- }
29
- value.set(element.value);
30
- }
31
4
 
5
+ export const handleElementAttributeClass = function(shouldAdd, _, __, context) {
6
+ context.element.classes.toggle(context.className, shouldAdd);
7
+ };
32
8
  /**
33
9
  *
34
10
  * @param {HTMLElement} element
35
11
  * @param {Object} data
36
12
  */
37
13
  export function bindClassAttribute(element, data) {
38
- for(let className in data) {
14
+ const classNames = Object.keys(data);
15
+
16
+ for(let i = 0, length = classNames.length; i < length; i++) {
17
+ const className = classNames[i];
39
18
  const value = data[className];
40
- if(Validator.isObservable(value)) {
19
+ if(value.__$isObservable) {
41
20
  element.classes.toggle(className, value.val());
42
- value.subscribe(toggleElementClass.bind(null, element, className));
21
+ value.subscribe(handleElementAttributeClass, { element, className });
22
+ // value.subscribe((shouldAdd) => element.classes.toggle(className, shouldAdd));
43
23
  continue;
44
24
  }
45
- if(Validator.isObservableWhenResult(value)) {
25
+ if(value.__$isObservableWhen) {
46
26
  element.classes.toggle(className, value.isMath());
47
- value.subscribe(toggleElementClass.bind(null, element, className));
27
+ value.subscribe(handleElementAttributeClass, { element, className });
48
28
  continue;
49
29
  }
50
30
  if(value.$hydrate) {
@@ -53,7 +33,6 @@ export function bindClassAttribute(element, data) {
53
33
  }
54
34
  element.classes.toggle(className, value)
55
35
  }
56
- data = null;
57
36
  }
58
37
 
59
38
  /**
@@ -62,11 +41,13 @@ export function bindClassAttribute(element, data) {
62
41
  * @param {Object} data
63
42
  */
64
43
  export function bindStyleAttribute(element, data) {
65
- for(let styleName in data) {
44
+ const keys = Object.keys(data)
45
+ for(let i = 0, length = keys.length; i < length; i++) {
46
+ const styleName = keys[i];
66
47
  const value = data[styleName];
67
- if(Validator.isObservable(value)) {
48
+ if(value.__$isObservable) {
68
49
  element.style[styleName] = value.val();
69
- value.subscribe(toggleElementStyle.bind(null, element, styleName));
50
+ value.subscribe((newValue) => element.style[styleName] = newValue);
70
51
  continue;
71
52
  }
72
53
  element.style[styleName] = value;
@@ -80,18 +61,27 @@ export function bindStyleAttribute(element, data) {
80
61
  * @param {boolean|number|Observable} value
81
62
  */
82
63
  export function bindBooleanAttribute(element, attributeName, value) {
83
- const defaultValue = Validator.isObservable(value) ? value.val() : value;
84
- if(Validator.isBoolean(defaultValue)) {
64
+ const isObservable = value.__$isObservable;
65
+ const defaultValue = isObservable? value.val() : value;
66
+ const isBoolValue = typeof defaultValue === "boolean";
67
+ if(isBoolValue) {
85
68
  element[attributeName] = defaultValue;
86
69
  }
87
70
  else {
88
71
  element[attributeName] = defaultValue === element.value;
89
72
  }
90
- if(Validator.isObservable(value)) {
91
- if(['checked'].includes(attributeName)) {
92
- element.addEventListener('input', updateObserverFromInput.bind(null, element, attributeName, defaultValue, value));
73
+ if(isObservable) {
74
+ if(attributeName === 'checked') {
75
+ if(isBoolValue) {
76
+ element.addEventListener('input', () => value.set(element[attributeName]));
77
+ value.subscribe((newValue) => element[attributeName] = newValue);
78
+ return;
79
+ }
80
+ element.addEventListener('input', () => value.set(element.value));
81
+ value.subscribe((newValue) => element[attributeName] = (newValue === element.value));
82
+ return;
93
83
  }
94
- value.subscribe(updateInputFromObserver.bind(null, element, attributeName));
84
+ value.subscribe((newValue) => element[attributeName] = (newValue === element.value));
95
85
  }
96
86
  }
97
87
 
@@ -103,19 +93,15 @@ export function bindBooleanAttribute(element, attributeName, value) {
103
93
  * @param {Observable} value
104
94
  */
105
95
  export function bindAttributeWithObservable(element, attributeName, value) {
106
- const applyValue = (newValue) => {
107
- if(attributeName === 'value') {
108
- element.value = newValue;
109
- return;
110
- }
111
- element.setAttribute(attributeName, newValue);
112
- };
113
- applyValue(value.val());
114
- value.subscribe(applyValue);
115
-
116
96
  if(attributeName === 'value') {
97
+ value.subscribe((newValue) => element.value = newValue);
98
+ element.value = value.val();
117
99
  element.addEventListener('input', () => value.set(element.value));
100
+ return;
118
101
  }
102
+
103
+ value.subscribe((newValue) => element.setAttribute(attributeName, newValue));
104
+ element.setAttribute(attributeName, value.val());
119
105
  }
120
106
 
121
107
  /**
@@ -125,15 +111,15 @@ export function bindAttributeWithObservable(element, attributeName, value) {
125
111
  */
126
112
  export default function AttributesWrapper(element, attributes) {
127
113
 
128
- Validator.validateAttributes(attributes);
129
-
130
- if(!Validator.isObject(attributes)) {
131
- throw new NativeDocumentError('Attributes must be an object');
114
+ if(process.env.NODE_ENV === 'development') {
115
+ Validator.validateAttributes(attributes);
132
116
  }
117
+ const attributeNames = Object.keys(attributes);
133
118
 
134
- for(let key in attributes) {
135
- const attributeName = key.toLowerCase();
136
- let value = attributes[attributeName];
119
+ for(let i = 0, length = attributeNames.length; i < length; i++) {
120
+ const originalAttributeName = attributeNames[i];
121
+ const attributeName = originalAttributeName.toLowerCase();
122
+ let value = attributes[originalAttributeName];
137
123
  if(value == null) {
138
124
  continue;
139
125
  }
@@ -156,6 +142,10 @@ export default function AttributesWrapper(element, attributes) {
156
142
  continue;
157
143
  }
158
144
 
145
+ if(attributeName === 'value') {
146
+ element.value = value;
147
+ continue;
148
+ }
159
149
  element.setAttribute(attributeName, value);
160
150
  }
161
151
  return element;
@@ -69,6 +69,14 @@ export const ElementCreator = {
69
69
  }
70
70
  return Anchor('Fragment');
71
71
  },
72
+ bindTextNode(textNode, value) {
73
+ if(value?.__$isObservable) {
74
+ value.subscribe(newValue => textNode.nodeValue = newValue);
75
+ textNode.nodeValue = value.val();
76
+ return;
77
+ }
78
+ textNode.nodeValue = value;
79
+ },
72
80
  /**
73
81
  *
74
82
  * @param {*} children
@@ -1,5 +1,4 @@
1
1
  import {ElementCreator} from "./ElementCreator";
2
- import {createTextNode} from "./HtmlElementWrapper";
3
2
  import TemplateBinding from "./TemplateBinding";
4
3
 
5
4
  const cloneBindingsDataCache = new WeakMap();
@@ -65,9 +64,8 @@ const bindAttachMethods = function(node, bindDingData, data) {
65
64
 
66
65
 
67
66
  const applyBindingTreePath = (root, target, data, path) => {
68
- let newTarget = null;
69
67
  if(path.fn) {
70
- newTarget = path.fn(data, target, root);
68
+ path.fn(data, target, root);
71
69
  }
72
70
  if(path.children) {
73
71
  for(let i = 0, length = path.children.length; i < length; i++) {
@@ -76,7 +74,6 @@ const applyBindingTreePath = (root, target, data, path) => {
76
74
  applyBindingTreePath(root, pathTargetNode, data, currentPath);
77
75
  }
78
76
  }
79
- return newTarget;
80
77
  };
81
78
 
82
79
  export function TemplateCloner($fn) {
@@ -92,15 +89,10 @@ export function TemplateCloner($fn) {
92
89
  const bindDingData = cloneBindingsDataCache.get(node);
93
90
  if(node.nodeType === 3) {
94
91
  if(bindDingData && bindDingData.value) {
95
- currentPath.fn = (data, targetNode, currentRoot) => {
96
- const newNode = bindDingData.value(data);
97
- if (targetNode === currentRoot) {
98
- return newNode;
99
- }
100
- targetNode.replaceWith(newNode);
101
- return null;
102
- };
103
- return bindDingData.value(data);
92
+ currentPath.fn = bindDingData.value;
93
+ const textNode = node.cloneNode();
94
+ bindDingData.value(data, textNode);
95
+ return textNode;
104
96
  }
105
97
  return node.cloneNode(true);
106
98
  }
@@ -137,11 +129,7 @@ export function TemplateCloner($fn) {
137
129
  const cloneWithBindingPaths = (data) => {
138
130
  let root = $node.cloneNode(true);
139
131
 
140
- const newRoot = applyBindingTreePath(root, root, data, $bindingTreePath);
141
- if(newRoot) {
142
- root = newRoot;
143
- }
144
-
132
+ applyBindingTreePath(root, root, data, $bindingTreePath);
145
133
  return root;
146
134
  };
147
135
 
@@ -176,13 +164,13 @@ export function TemplateCloner($fn) {
176
164
  }
177
165
  this.value = (callbackOrProperty) => {
178
166
  if(typeof callbackOrProperty !== 'function') {
179
- return createBinding(function(data) {
167
+ return createBinding(function(data, textNode) {
180
168
  const firstArgument = data[0];
181
- return createTextNode(firstArgument[callbackOrProperty]);
169
+ ElementCreator.bindTextNode(textNode, firstArgument[callbackOrProperty]);
182
170
  }, 'value');
183
171
  }
184
- return createBinding(function(data) {
185
- return createTextNode(callbackOrProperty(...data));
172
+ return createBinding(function(data, textNode) {
173
+ ElementCreator.bindTextNode(textNode, callbackOrProperty(...data));
186
174
  }, 'value');
187
175
  };
188
176
  this.attr = (fn) => {
@@ -1,16 +1,20 @@
1
1
  import ObservableItem from "../../../core/data/ObservableItem";
2
- import {toggleElementClass} from "../AttributesWrapper";
3
2
  import {ObservableWhen} from "../../data/ObservableWhen";
4
3
  import TemplateBinding from "../../../core/wrappers/TemplateBinding";
5
4
 
5
+
6
+ export const handleElementAttributeClass = function(shouldAdd, _, __, context) {
7
+ context.element.classes.toggle(context.className, shouldAdd);
8
+ };
9
+
6
10
  ObservableItem.prototype.bindNdClass = function(element, className) {
7
11
  element.classes.toggle(className, this.val());
8
- this.subscribe(toggleElementClass.bind(null, element, className));
12
+ this.subscribe(handleElementAttributeClass, { element, className });
9
13
  };
10
14
 
11
15
  ObservableWhen.prototype.bindNdClass = function(element, className) {
12
16
  element.classes.toggle(className, this.isMath());
13
- this.subscribe(toggleElementClass.bind(null, element, className));
17
+ this.subscribe(handleElementAttributeClass, { element, className });
14
18
  };
15
19
 
16
20
  TemplateBinding.prototype.bindNdClass = function(element, className) {