@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/README.md +17 -1
- package/dist/fore-all.js +10 -10
- package/dist/fore.js +1 -1
- package/index.js +8 -0
- package/package.json +4 -1
- package/resources/fore.css +111 -1
- package/src/DependencyNotifyingDomFacade.js +9 -1
- package/src/ForeElementMixin.js +25 -17
- package/src/actions/abstract-action.js +8 -7
- package/src/actions/fx-action.js +6 -1
- package/src/actions/fx-dispatch.js +10 -2
- package/src/actions/fx-hide.js +23 -0
- package/src/actions/fx-insert.js +14 -10
- package/src/actions/fx-send.js +1 -1
- package/src/actions/fx-setvalue.js +2 -4
- package/src/actions/fx-show.js +23 -0
- package/src/dep_graph.js +9 -0
- package/src/drawdown.js +172 -0
- package/src/fore.js +94 -3
- package/src/functions/fx-function.js +2 -2
- package/src/fx-bind.js +20 -17
- package/src/fx-fore.js +306 -33
- package/src/fx-instance.js +27 -6
- package/src/fx-model.js +182 -41
- package/src/fx-submission.js +29 -7
- package/src/fx-var.js +43 -0
- package/src/getInScopeContext.js +28 -7
- package/src/modelitem.js +1 -0
- package/src/ui/abstract-control.js +21 -6
- package/src/ui/fx-alert.js +16 -20
- package/src/ui/fx-container.js +9 -4
- package/src/ui/fx-control.js +76 -39
- package/src/ui/fx-dialog.js +68 -0
- package/src/ui/fx-inspector.js +44 -0
- package/src/ui/fx-items.js +120 -0
- package/src/ui/fx-output.js +77 -9
- package/src/ui/fx-repeat.js +86 -16
- package/src/ui/fx-repeatitem.js +16 -3
- package/src/ui/fx-trigger.js +3 -0
- package/src/xpath-evaluation.js +609 -267
- package/src/xpath-util.js +52 -12
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-
|
|
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
|
-
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this.
|
|
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
|
-
|
|
256
|
-
|
|
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.
|
|
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) {
|