@jinntec/fore 1.0.0-0 → 1.0.0-3

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/src/fore.js CHANGED
@@ -34,6 +34,21 @@ export class Fore {
34
34
  ];
35
35
  }
36
36
 
37
+ static createUUID() {
38
+ // http://www.ietf.org/rfc/rfc4122.txt
39
+ const s = [];
40
+ const hexDigits = '0123456789abcdef';
41
+ for (let i = 0; i < 36; i += 1) {
42
+ s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
43
+ }
44
+ s[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010
45
+ s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
46
+ s[8] = s[13] = s[18] = s[23] = '-';
47
+
48
+ const uuid = s.join('');
49
+ return uuid;
50
+ }
51
+
37
52
  static get XFORMS_NAMESPACE_URI() {
38
53
  // todo: should be centralized somewhere as constant. Exists in several? places
39
54
  return 'http://www.w3.org/2002/xforms';
@@ -55,7 +70,7 @@ export class Fore {
55
70
  'FX-GROUP',
56
71
  'FX-HINT',
57
72
  'FX-INPUT',
58
- 'FX-ITEMSET',
73
+ 'FX-ITEMS',
59
74
  'FX-LABEL',
60
75
  'FX-OUTPUT',
61
76
  'FX-RANGE',
@@ -68,6 +83,7 @@ export class Fore {
68
83
  'FX-TEXTAREA',
69
84
  'FX-TRIGGER',
70
85
  'FX-UPLOAD',
86
+ 'FX-VAR',
71
87
  ];
72
88
  }
73
89
 
@@ -79,15 +95,40 @@ export class Fore {
79
95
  return Fore.UI_ELEMENTS.includes(elementName);
80
96
  }
81
97
 
82
- static async refreshChildren(startElement) {
98
+ /**
99
+ * recursively refreshes all UI Elements.
100
+ *
101
+ * todo: this could probably made more efficient with significant impact on rendering perf
102
+ *
103
+ * @param startElement
104
+ * @param force
105
+ * @returns {Promise<unknown>}
106
+ */
107
+ static async refreshChildren(startElement, force) {
83
108
  const refreshed = new Promise(resolve => {
109
+ /*
110
+ if there's an 'refresh-on-view' attribute the element wants to be handled by
111
+ handleIntersect function that calls the refresh of the respective element and
112
+ not the global one.
113
+ */
114
+ // if(!force && startElement.hasAttribute('refresh-on-view')) return;
115
+
116
+ /* ### attempt with querySelectorAll is even slower than iterating recursively
117
+
118
+ const children = startElement.querySelectorAll('[ref]');
119
+ Array.from(children).forEach(uiElement => {
120
+ if (Fore.isUiElement(uiElement.nodeName) && typeof uiElement.refresh === 'function') {
121
+ uiElement.refresh();
122
+ }
123
+ });
124
+ */
84
125
  const { children } = startElement;
85
126
  if (children) {
86
127
  Array.from(children).forEach(element => {
87
128
  if (Fore.isUiElement(element.nodeName) && typeof element.refresh === 'function') {
88
129
  element.refresh();
89
130
  } else if (element.nodeName.toUpperCase() !== 'FX-MODEL') {
90
- Fore.refreshChildren(element);
131
+ Fore.refreshChildren(element, force);
91
132
  }
92
133
  });
93
134
  }
@@ -127,6 +168,56 @@ export class Fore {
127
168
  return null;
128
169
  }
129
170
 
171
+ static fadeInElement(element) {
172
+ const duration = 600;
173
+ let fadeIn = () => {
174
+ // Stop all current animations
175
+ if (element.getAnimations) {
176
+ element.getAnimations().map(anim => anim.finish());
177
+ }
178
+
179
+ // Play the animation with the newly specified duration
180
+ fadeIn = element.animate(
181
+ {
182
+ opacity: [0, 1],
183
+ },
184
+ duration,
185
+ );
186
+ return fadeIn.finished;
187
+ };
188
+ return fadeIn();
189
+ }
190
+
191
+ static fadeOutElement(element) {
192
+ const duration = 2600;
193
+ let fadeOut = () => {
194
+ // Stop all current animations
195
+ if (element.getAnimations) {
196
+ element.getAnimations().map(anim => anim.finish());
197
+ }
198
+
199
+ // Play the animation with the newly specified duration
200
+ fadeOut = element.animate(
201
+ {
202
+ opacity: [1, 0],
203
+ },
204
+ duration,
205
+ );
206
+ return fadeOut.finished;
207
+ };
208
+ return fadeOut();
209
+ }
210
+
211
+ static dispatch(target, eventName, detail) {
212
+ const event = new CustomEvent(eventName, {
213
+ composed: true,
214
+ bubbles: true,
215
+ detail,
216
+ });
217
+ console.log('firing', event);
218
+ target.dispatchEvent(event);
219
+ }
220
+
130
221
  /**
131
222
  * clear all text nodes and attribute values to get a 'clean' template.
132
223
  * @param n
@@ -28,9 +28,9 @@ export class FxFunction extends foreElementMixin(HTMLElement) {
28
28
  const type = this.getAttribute('type') || 'text/xpath';
29
29
 
30
30
  // Parse the signature to something useful
31
- // Signature is of the form `my:sumproduct($p as xs:decimal*, $q as xs:decimal*) as xs:decimal`
31
+ // Signature is of the form `my:sumproduct($p as xs:decimal*, $q as xs:decimal*) as xs:decimal` or local:something($a as item()*) as item()*
32
32
  const signatureParseResult = this.signature.match(
33
- /(?:(?<prefix>[^:]*):)?(?<localName>[^(]+)\((?<params>[^)]*)\)(?: as (?<returnType>.*))?/,
33
+ /(?:(?<prefix>[^:]*):)?(?<localName>[^(]+)\((?<params>(?:\(\)|[^)])*)\)(?: as (?<returnType>.*))?/,
34
34
  );
35
35
 
36
36
  if (!signatureParseResult) {
package/src/fx-bind.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  evaluateXPathToString,
8
8
  } from './xpath-evaluation.js';
9
9
  import { XPathUtil } from './xpath-util.js';
10
+ import getInScopeContext from './getInScopeContext.js';
10
11
 
11
12
  /**
12
13
  * FxBind declaratively attaches constraints to nodes in the data (instances).
@@ -182,12 +183,11 @@ export class FxBind extends foreElementMixin(HTMLElement) {
182
183
  if (this.bindType === 'xml') {
183
184
  this.nodeset.forEach(node => {
184
185
  const path = XPathUtil.getPath(node);
186
+ this.model.mainGraph.addNode(path, node);
185
187
 
186
188
  if (this.calculate) {
187
189
  this.model.mainGraph.addNode(`${path}:calculate`, node);
188
190
  // Calculated values are a dependency of the model item.
189
- // Make `model1` depend on `model1:calculate`
190
- this.model.mainGraph.addNode(path, node);
191
191
  this.model.mainGraph.addDependency(path, `${path}:calculate`);
192
192
  }
193
193
 
@@ -196,11 +196,13 @@ export class FxBind extends foreElementMixin(HTMLElement) {
196
196
  this._addDependencies(calculateRefs, node, path, 'calculate');
197
197
  }
198
198
 
199
- const readonlyRefs = this._getReferencesForProperty(this.readonly, node);
200
- if (readonlyRefs.length !== 0) {
201
- this._addDependencies(readonlyRefs, node, path, 'readonly');
202
- } else if (this.readonly) {
203
- this.model.mainGraph.addNode(`${path}:readonly`, node);
199
+ if (!this.calculate) {
200
+ const readonlyRefs = this._getReferencesForProperty(this.readonly, node);
201
+ if (readonlyRefs.length !== 0) {
202
+ this._addDependencies(readonlyRefs, node, path, 'readonly');
203
+ } else if (this.readonly) {
204
+ this.model.mainGraph.addNode(`${path}:readonly`, node);
205
+ }
204
206
  }
205
207
 
206
208
  // const requiredRefs = this.requiredReferences;
@@ -228,12 +230,6 @@ export class FxBind extends foreElementMixin(HTMLElement) {
228
230
  }
229
231
  }
230
232
 
231
- _addNode(path, node) {
232
- if (!this.model.mainGraph.hasNode(path)) {
233
- this.model.mainGraph.addNode(path, { node });
234
- }
235
- }
236
-
237
233
  /**
238
234
  * Add the dependencies of this bind
239
235
  *
@@ -244,6 +240,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
244
240
  * @param {string} property The property with this dependency
245
241
  */
246
242
  _addDependencies(refs, node, path, property) {
243
+ // console.log('_addDependencies',path);
247
244
  const nodeHash = `${path}:${property}`;
248
245
  if (refs.length !== 0) {
249
246
  if (!this.model.mainGraph.hasNode(nodeHash)) {
@@ -251,11 +248,15 @@ export class FxBind extends foreElementMixin(HTMLElement) {
251
248
  }
252
249
  refs.forEach(ref => {
253
250
  const otherPath = XPathUtil.getPath(ref);
251
+ // console.log('otherPath', otherPath)
254
252
 
255
- if (!this.model.mainGraph.hasNode(otherPath)) {
256
- this.model.mainGraph.addNode(otherPath, ref);
253
+ // todo: nasty hack to prevent duplicate pathes like 'a[1]' and 'a[1]/text()[1]' to end up as separate nodes in the graph
254
+ if(!otherPath.endsWith('text()[1]')){
255
+ if (!this.model.mainGraph.hasNode(otherPath)) {
256
+ this.model.mainGraph.addNode(otherPath, ref);
257
+ }
258
+ this.model.mainGraph.addDependency(nodeHash, otherPath);
257
259
  }
258
- this.model.mainGraph.addDependency(nodeHash, otherPath);
259
260
  });
260
261
  } else {
261
262
  this.model.mainGraph.addNode(nodeHash, node);
@@ -320,7 +321,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
320
321
  * overwrites
321
322
  */
322
323
  _evalInContext() {
323
- const inscopeContext = this.getInScopeContext();
324
+ const inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
324
325
 
325
326
  // reset nodeset
326
327
  this.nodeset = [];
@@ -508,6 +509,8 @@ export class FxBind extends foreElementMixin(HTMLElement) {
508
509
  * @param {string} propertyExpr The XPath to get the referenced nodes from
509
510
  *
510
511
  * @return {Node[]} The nodes that are referenced by the XPath
512
+ *
513
+ * todo: DependencyNotifyingDomFacade reports back too much in some cases like 'a[1]' and 'a[1]/text[1]'
511
514
  */
512
515
  _getReferencesForProperty(propertyExpr) {
513
516
  if (propertyExpr) {