@jinntec/fore 1.10.3 → 2.0.0
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/dist/fore-dev.js +2 -2
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +2 -2
- package/dist/fore.js.map +1 -1
- package/package.json +1 -1
- package/src/actions/abstract-action.js +1 -1
- package/src/actions/fx-load.js +3 -35
- package/src/actions/fx-refresh.js +3 -0
- package/src/actions/fx-toggle.js +1 -1
- package/src/fore.js +77 -2
- package/src/fx-fore.js +68 -65
- package/src/fx-instance.js +1 -0
- package/src/fx-model.js +32 -10
- package/src/fx-submission.js +1 -1
- package/src/getInScopeContext.js +0 -4
- package/src/ui/fx-case.js +5 -2
- package/src/ui/fx-container.js +22 -0
- package/src/ui/fx-control.js +25 -31
- package/src/ui/fx-inspector.js +16 -12
- package/src/ui/fx-repeat.js +2 -1
- package/src/ui/fx-switch.js +7 -2
package/package.json
CHANGED
package/src/actions/fx-load.js
CHANGED
|
@@ -5,10 +5,9 @@ import {XPathUtil} from "../xpath-util.js";
|
|
|
5
5
|
import {Fore} from "../fore.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* `fx-
|
|
9
|
-
*
|
|
10
|
-
* Action to display messages to the user.
|
|
8
|
+
* `fx-load`
|
|
11
9
|
*
|
|
10
|
+
* Action to load a window, tab or embed some Html into the current page at given location.
|
|
12
11
|
*
|
|
13
12
|
*/
|
|
14
13
|
class FxLoad extends AbstractAction {
|
|
@@ -145,24 +144,14 @@ class FxLoad extends AbstractAction {
|
|
|
145
144
|
});
|
|
146
145
|
const data = await response.text();
|
|
147
146
|
// console.log('data loaded: ', data);
|
|
147
|
+
// const data = Fore.loadHtml(resolvedUrl);
|
|
148
148
|
|
|
149
149
|
// todo: if data contain '<template' element as first child instanciate and insert it
|
|
150
150
|
if (!this.attachTo) {
|
|
151
151
|
this.innerHtml = data;
|
|
152
152
|
}
|
|
153
|
-
/*
|
|
154
|
-
if (this.attachTo.startsWith('#')) {
|
|
155
|
-
const targetId = this.attachTo.substring(1);
|
|
156
|
-
const resolved = resolveId(targetId, this);
|
|
157
|
-
resolved.innerHTML = '';
|
|
158
|
-
resolved.innerHTML = data;
|
|
159
|
-
}
|
|
160
|
-
*/
|
|
161
153
|
this._attachToElement(data);
|
|
162
|
-
|
|
163
|
-
|
|
164
154
|
Fore.dispatch(this, 'loaded', {url: this.url})
|
|
165
|
-
|
|
166
155
|
} catch (error) {
|
|
167
156
|
throw new Error(`failed loading data ${error}`);
|
|
168
157
|
}
|
|
@@ -228,27 +217,6 @@ class FxLoad extends AbstractAction {
|
|
|
228
217
|
return replaced;
|
|
229
218
|
}
|
|
230
219
|
|
|
231
|
-
|
|
232
|
-
/*
|
|
233
|
-
_getValue() {
|
|
234
|
-
if (this.hasAttribute('value')) {
|
|
235
|
-
const valAttr = this.getAttribute('value');
|
|
236
|
-
try {
|
|
237
|
-
const inscopeContext = getInScopeContext(this, valAttr);
|
|
238
|
-
return evaluateXPathToString(valAttr, inscopeContext, this);
|
|
239
|
-
} catch (error) {
|
|
240
|
-
console.error(error);
|
|
241
|
-
Fore.dispatch(this, 'error', {message: error});
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (this.textContent) {
|
|
245
|
-
return this.textContent;
|
|
246
|
-
}
|
|
247
|
-
return null;
|
|
248
|
-
}
|
|
249
|
-
*/
|
|
250
|
-
|
|
251
|
-
|
|
252
220
|
}
|
|
253
221
|
|
|
254
222
|
if (!customElements.get('fx-load')) {
|
|
@@ -21,6 +21,7 @@ class FxRefresh extends AbstractAction {
|
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
if (this.hasAttribute('self')) {
|
|
24
|
+
console.log(`### <<<<< refresh() self ${this} >>>>>`);
|
|
24
25
|
const control = XPathUtil.getClosest('fx-control', this);
|
|
25
26
|
if (control) {
|
|
26
27
|
control.refresh();
|
|
@@ -28,11 +29,13 @@ class FxRefresh extends AbstractAction {
|
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
if(this.hasAttribute('force')){
|
|
32
|
+
console.log(`### <<<<< refresh() force ${this} >>>>>`);
|
|
31
33
|
this.getOwnerForm().forceRefresh();
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
if(this.hasAttribute('control')){
|
|
35
37
|
const targetId = this.getAttribute('control');
|
|
38
|
+
console.log(`### <<<<< refresh() control '${targetId}' >>>>>`);
|
|
36
39
|
const ctrl = resolveId(targetId, this);
|
|
37
40
|
if (ctrl && Fore.isUiElement(ctrl.nodeName) && typeof ctrl.refresh === 'function') {
|
|
38
41
|
ctrl.refresh();
|
package/src/actions/fx-toggle.js
CHANGED
package/src/fore.js
CHANGED
|
@@ -18,6 +18,79 @@ export class Fore {
|
|
|
18
18
|
|
|
19
19
|
static TYPE_DEFAULT = 'xs:string';
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Loads and return a piece of HTML
|
|
23
|
+
* @param url - the Url to load from
|
|
24
|
+
* @returns {Promise<string>}
|
|
25
|
+
*/
|
|
26
|
+
static async loadHtml(url){
|
|
27
|
+
try{
|
|
28
|
+
const response = await fetch(url, {
|
|
29
|
+
method: 'GET',
|
|
30
|
+
mode: 'cors',
|
|
31
|
+
credentials: 'same-origin',
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': "text/html",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const responseContentType = response.headers.get('content-type').toLowerCase();
|
|
37
|
+
if (responseContentType.startsWith('text/html')) {
|
|
38
|
+
return response.text();
|
|
39
|
+
} else {
|
|
40
|
+
Fore.dispatch(this, 'error', {
|
|
41
|
+
message: `Response has wrong contentType '${responseContentType}'. Should be 'text/html'`,
|
|
42
|
+
level:'Error'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
} catch (e){
|
|
46
|
+
Fore.dispatch(this, 'error', {
|
|
47
|
+
message: `Html couldn't be loaded from '${url}'`,
|
|
48
|
+
level:'Error'
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* loads a Fore element from given `src`. Always returns the first occurrence of a `<fx-fore>`. The retured element
|
|
55
|
+
* will replace the `replace` element in the DOM.
|
|
56
|
+
*
|
|
57
|
+
* @param replace the element with a `src` attribute to resolvé.
|
|
58
|
+
* @param src the Url to resolve
|
|
59
|
+
* @param selector a querySelector expression to fetch certain element from loaded document
|
|
60
|
+
* @returns {Promise<void>}
|
|
61
|
+
*/
|
|
62
|
+
static async loadForeFromSrc(replace, src, selector){
|
|
63
|
+
if(!src){
|
|
64
|
+
Fore.dispatch(this, 'error', {
|
|
65
|
+
detail: {
|
|
66
|
+
message: `No 'src' attribute present`,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
await Fore.loadHtml(src)
|
|
71
|
+
.then(data => {
|
|
72
|
+
const parsed = new DOMParser().parseFromString(data, 'text/html');
|
|
73
|
+
// const theFore = parsed.querySelector('fx-fore');
|
|
74
|
+
const foreElement = parsed.querySelector(selector);
|
|
75
|
+
// console.log('foreElement', foreElement)
|
|
76
|
+
if (!foreElement) {
|
|
77
|
+
Fore.dispatch(this, 'error', {
|
|
78
|
+
detail: {
|
|
79
|
+
message: `Fore element not found in '${src}'. Maybe wrapped within 'template' element?`,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
foreElement.setAttribute('from-src', src);
|
|
84
|
+
const thisAttrs = replace.attributes;
|
|
85
|
+
Array.from(thisAttrs).forEach(attr =>{
|
|
86
|
+
if(attr.name !== 'src'){
|
|
87
|
+
foreElement.setAttribute(attr.name,attr.value);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
replace.replaceWith(foreElement);
|
|
91
|
+
return foreElement;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
21
94
|
static buildPredicates(node){
|
|
22
95
|
let attrPredicate='';
|
|
23
96
|
Array.from(node.attributes).forEach(attr =>{
|
|
@@ -467,6 +540,7 @@ export class Fore {
|
|
|
467
540
|
static stringifiedComponent(element){
|
|
468
541
|
return `<${element.localName} ${Array.from(element.attributes).map(attr=>`${attr.name}="${attr.value}"`).join(' ')}>…</${element.localName}>`;
|
|
469
542
|
}
|
|
543
|
+
/*
|
|
470
544
|
static async loadForeFromUrl(hostElement, url) {
|
|
471
545
|
// console.log('########## loading Fore from ', this.src, '##########');
|
|
472
546
|
await fetch(url, {
|
|
@@ -538,7 +612,7 @@ export class Fore {
|
|
|
538
612
|
// this.appendChild(imported);
|
|
539
613
|
}
|
|
540
614
|
})
|
|
541
|
-
|
|
615
|
+
/!*.catch(error => {
|
|
542
616
|
hostElement.dispatchEvent(
|
|
543
617
|
new CustomEvent('error', {
|
|
544
618
|
composed: false,
|
|
@@ -549,8 +623,9 @@ export class Fore {
|
|
|
549
623
|
},
|
|
550
624
|
}),
|
|
551
625
|
);
|
|
552
|
-
})
|
|
626
|
+
});*!/
|
|
553
627
|
}
|
|
628
|
+
*/
|
|
554
629
|
|
|
555
630
|
/**
|
|
556
631
|
* clear all text nodes and attribute values to get a 'clean' template.
|
package/src/fx-fore.js
CHANGED
|
@@ -56,6 +56,9 @@ export class FxFore extends HTMLElement {
|
|
|
56
56
|
ready: {
|
|
57
57
|
type: Boolean,
|
|
58
58
|
},
|
|
59
|
+
strict:{
|
|
60
|
+
type: Boolean
|
|
61
|
+
},
|
|
59
62
|
/**
|
|
60
63
|
*
|
|
61
64
|
*/
|
|
@@ -204,7 +207,7 @@ export class FxFore extends HTMLElement {
|
|
|
204
207
|
|
|
205
208
|
this.toRefresh = [];
|
|
206
209
|
this.initialRun = true;
|
|
207
|
-
this.
|
|
210
|
+
this._scanForNewTemplateExpressionsNextRefresh = false;
|
|
208
211
|
this.repeatsFromAttributesCreated = false;
|
|
209
212
|
this.validateOn = this.hasAttribute('validate-on') ? this.getAttribute('validate-on'):'update';
|
|
210
213
|
// this.mergePartial = this.hasAttribute('merge-partial')? true:false;
|
|
@@ -214,6 +217,7 @@ export class FxFore extends HTMLElement {
|
|
|
214
217
|
connectedCallback() {
|
|
215
218
|
this.style.visibility = 'hidden';
|
|
216
219
|
console.time('init');
|
|
220
|
+
this.strict = this.hasAttribute('strict') ? true : false;
|
|
217
221
|
/*
|
|
218
222
|
document.addEventListener('ready', (e) =>{
|
|
219
223
|
if(e.target !== this){
|
|
@@ -255,6 +259,7 @@ export class FxFore extends HTMLElement {
|
|
|
255
259
|
const slot = this.shadowRoot.querySelector('slot#default');
|
|
256
260
|
slot.addEventListener('slotchange', async event => {
|
|
257
261
|
// preliminary addition for auto-conversion of non-prefixed element into prefixed elements. See fore.js
|
|
262
|
+
console.log(`### <<<<< slotchange on '${this.id}' >>>>>`);
|
|
258
263
|
if(this.inited) return;
|
|
259
264
|
if(this.hasAttribute('convert')){
|
|
260
265
|
this.replaceWith(Fore.copyDom(this));
|
|
@@ -280,8 +285,8 @@ export class FxFore extends HTMLElement {
|
|
|
280
285
|
}
|
|
281
286
|
if (!modelElement.inited) {
|
|
282
287
|
console.info(
|
|
283
|
-
|
|
284
|
-
"background:#64b5f6; color:white; padding
|
|
288
|
+
`%cFore is processing fx-fore#${this.id}`,
|
|
289
|
+
"background:#64b5f6; color:white; padding:.5rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;",
|
|
285
290
|
);
|
|
286
291
|
|
|
287
292
|
await modelElement.modelConstruct();
|
|
@@ -296,6 +301,9 @@ export class FxFore extends HTMLElement {
|
|
|
296
301
|
this.addEventListener('path-mutated', () => {
|
|
297
302
|
this.someInstanceDataStructureChanged = true;
|
|
298
303
|
});
|
|
304
|
+
this.addEventListener('refresh', () => {
|
|
305
|
+
this.refresh(true);
|
|
306
|
+
});
|
|
299
307
|
|
|
300
308
|
}
|
|
301
309
|
|
|
@@ -319,6 +327,15 @@ export class FxFore extends HTMLElement {
|
|
|
319
327
|
}
|
|
320
328
|
}
|
|
321
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Raise a flag that there might be new template expressions under some node. This happens with
|
|
332
|
+
* repeats updating (new repeat items can have new template expressions) or switches changing their case (new case = new raw HTML)
|
|
333
|
+
*/
|
|
334
|
+
scanForNewTemplateExpressionsNextRefresh() {
|
|
335
|
+
// TODO: also ask for the root of any new HTML: this can prevent some very deep queries.
|
|
336
|
+
this._scanForNewTemplateExpressionsNextRefresh = true;
|
|
337
|
+
}
|
|
338
|
+
|
|
322
339
|
/**
|
|
323
340
|
* loads a Fore from an URL given by `src`.
|
|
324
341
|
*
|
|
@@ -327,54 +344,7 @@ export class FxFore extends HTMLElement {
|
|
|
327
344
|
*/
|
|
328
345
|
async _loadFromSrc() {
|
|
329
346
|
// console.log('########## loading Fore from ', this.src, '##########');
|
|
330
|
-
await
|
|
331
|
-
method: 'GET',
|
|
332
|
-
mode: 'cors',
|
|
333
|
-
credentials: 'include',
|
|
334
|
-
headers: {
|
|
335
|
-
'Content-Type': 'text/html',
|
|
336
|
-
},
|
|
337
|
-
})
|
|
338
|
-
.then(response => {
|
|
339
|
-
const responseContentType = response.headers.get('content-type').toLowerCase();
|
|
340
|
-
console.log('********** responseContentType *********', responseContentType);
|
|
341
|
-
if (responseContentType.startsWith('text/html')) {
|
|
342
|
-
// const htmlResponse = response.text();
|
|
343
|
-
// return new DOMParser().parseFromString(htmlResponse, 'text/html');
|
|
344
|
-
// return response.text();
|
|
345
|
-
return response.text().then(result =>
|
|
346
|
-
// console.log('xml ********', result);
|
|
347
|
-
new DOMParser().parseFromString(result, 'text/html'),
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
return 'done';
|
|
351
|
-
})
|
|
352
|
-
.then(data => {
|
|
353
|
-
// const theFore = fxEvaluateXPathToFirstNode('//fx-fore', data.firstElementChild);
|
|
354
|
-
const theFore = data.querySelector('fx-fore');
|
|
355
|
-
|
|
356
|
-
// console.log('thefore', theFore)
|
|
357
|
-
if (!theFore) {
|
|
358
|
-
Fore.dispatch(this, 'error', {
|
|
359
|
-
detail: {
|
|
360
|
-
message: `Fore element not found in '${this.src}'. Maybe wrapped within 'template' element?`,
|
|
361
|
-
},
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
theFore.setAttribute('from-src', this.src);
|
|
365
|
-
const thisAttrs = this.attributes;
|
|
366
|
-
Array.from(thisAttrs).forEach(attr =>{
|
|
367
|
-
if(attr.name !== 'src'){
|
|
368
|
-
theFore.setAttribute(attr.name,attr.value);
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
this.replaceWith(theFore);
|
|
372
|
-
})
|
|
373
|
-
.catch(() => {
|
|
374
|
-
Fore.dispatch(this, 'error', {
|
|
375
|
-
message: `'${this.src}' not found or does not contain Fore element.`,
|
|
376
|
-
});
|
|
377
|
-
});
|
|
347
|
+
await Fore.loadForeFromSrc(this,this.src,'fx-fore');
|
|
378
348
|
}
|
|
379
349
|
|
|
380
350
|
/**
|
|
@@ -443,8 +413,11 @@ export class FxFore extends HTMLElement {
|
|
|
443
413
|
|
|
444
414
|
Fore.refreshChildren(this, true);
|
|
445
415
|
this._updateTemplateExpressions();
|
|
446
|
-
this.
|
|
416
|
+
this._scanForNewTemplateExpressionsNextRefresh = false; // reset
|
|
447
417
|
this._processTemplateExpressions();
|
|
418
|
+
|
|
419
|
+
console.log(`### <<<<< refresh-done ${this.id} >>>>>`);
|
|
420
|
+
|
|
448
421
|
Fore.dispatch(this, 'refresh-done', {});
|
|
449
422
|
|
|
450
423
|
// console.groupEnd();
|
|
@@ -493,7 +466,7 @@ export class FxFore extends HTMLElement {
|
|
|
493
466
|
return;
|
|
494
467
|
}
|
|
495
468
|
this.isRefreshing = true;
|
|
496
|
-
console.log(
|
|
469
|
+
console.log(`### <<<<< refresh() on '${this.id}' >>>>>`);
|
|
497
470
|
|
|
498
471
|
// refresh () {
|
|
499
472
|
// ### refresh Fore UI elements
|
|
@@ -553,9 +526,9 @@ export class FxFore extends HTMLElement {
|
|
|
553
526
|
}
|
|
554
527
|
|
|
555
528
|
// ### refresh template expressions
|
|
556
|
-
if (this.initialRun || this.
|
|
529
|
+
if (this.initialRun || this._scanForNewTemplateExpressionsNextRefresh) {
|
|
557
530
|
this._updateTemplateExpressions();
|
|
558
|
-
this.
|
|
531
|
+
this._scanForNewTemplateExpressionsNextRefresh = false; // reset
|
|
559
532
|
}
|
|
560
533
|
this._processTemplateExpressions();
|
|
561
534
|
|
|
@@ -563,14 +536,33 @@ export class FxFore extends HTMLElement {
|
|
|
563
536
|
// this.dispatchEvent(new CustomEvent('refresh-done'));
|
|
564
537
|
// this.initialRun = false;
|
|
565
538
|
this.style.visibility='visible';
|
|
539
|
+
console.log(`### <<<<< refresh-done ${this.id} >>>>>`);
|
|
566
540
|
Fore.dispatch(this, 'refresh-done', {});
|
|
567
541
|
|
|
568
542
|
// this.isRefreshing = true;
|
|
569
543
|
// this.parentNode.closest('fx-fore')?.refresh(false, changedPaths);
|
|
570
|
-
|
|
571
|
-
|
|
544
|
+
|
|
545
|
+
const subFores = Array.from(this.querySelectorAll('fx-fore'));
|
|
546
|
+
/*
|
|
547
|
+
calling the parent to refresh causes errors and inconsistent state. Also it is questionable
|
|
548
|
+
if a child should actually interact with its parent in this way.
|
|
549
|
+
|
|
550
|
+
This only affects the refreshing NOT the data mutation itself which is happening as expected.
|
|
551
|
+
|
|
552
|
+
Current solution is that a child that wants the parent to refresh must do so by adding an additional
|
|
553
|
+
event handler that dispatches an event upwards and having a handler in the parent to refresh itself.
|
|
554
|
+
|
|
555
|
+
So refreshed propagate downwards but not upwards which is at least an option to consider.
|
|
556
|
+
|
|
557
|
+
if(this.parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE){
|
|
558
|
+
// await this.parentNode.closest('fx-fore')?.refresh(false);
|
|
559
|
+
}
|
|
560
|
+
*/
|
|
561
|
+
for (const subFore of subFores) {
|
|
572
562
|
// subFore.refresh(false, changedPaths);
|
|
573
|
-
|
|
563
|
+
if(subFore.ready){
|
|
564
|
+
await subFore.refresh(false);
|
|
565
|
+
}
|
|
574
566
|
}
|
|
575
567
|
this.isRefreshing = false;
|
|
576
568
|
}
|
|
@@ -672,11 +664,11 @@ export class FxFore extends HTMLElement {
|
|
|
672
664
|
const naked = match.substring(1, match.length - 1);
|
|
673
665
|
const inscope = getInScopeContext(node, naked);
|
|
674
666
|
if (!inscope) {
|
|
667
|
+
console.warn('no inscope context for expr', naked);
|
|
675
668
|
const errNode =
|
|
676
669
|
node.nodeType === Node.TEXT_NODE || node.nodeType === Node.ATTRIBUTE_NODE
|
|
677
670
|
? node.parentNode
|
|
678
671
|
: node;
|
|
679
|
-
console.warn('no inscope context for ', errNode);
|
|
680
672
|
return match;
|
|
681
673
|
}
|
|
682
674
|
// Templates are special: they use the namespace configuration from the place where they are
|
|
@@ -695,11 +687,17 @@ export class FxFore extends HTMLElement {
|
|
|
695
687
|
}
|
|
696
688
|
});
|
|
697
689
|
|
|
690
|
+
// Update to the new value. Don't do it though if nothing changed to prevent iframes or
|
|
691
|
+
// images from reloading for example
|
|
698
692
|
if (node.nodeType === Node.ATTRIBUTE_NODE) {
|
|
699
693
|
const parent = node.ownerElement;
|
|
700
|
-
|
|
694
|
+
if (parent.getAttribute(node.nodeName) !== replaced) {
|
|
695
|
+
parent.setAttribute(node.nodeName, replaced);
|
|
696
|
+
}
|
|
701
697
|
} else if (node.nodeType === Node.TEXT_NODE) {
|
|
702
|
-
|
|
698
|
+
if (node.textContent !== replaced) {
|
|
699
|
+
node.textContent = replaced;
|
|
700
|
+
}
|
|
703
701
|
}
|
|
704
702
|
}
|
|
705
703
|
|
|
@@ -770,7 +768,11 @@ export class FxFore extends HTMLElement {
|
|
|
770
768
|
const model = this.querySelector('fx-model');
|
|
771
769
|
|
|
772
770
|
// ##### lazy creation should NOT take place if there's a parent Fore using shared instances
|
|
773
|
-
const parentFore = this.parentNode.closest('fx-fore');
|
|
771
|
+
const parentFore = this.parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE ? this.parentNode.closest('fx-fore'): null;
|
|
772
|
+
if(this.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE){
|
|
773
|
+
console.log('fragment',this.parentNode)
|
|
774
|
+
}
|
|
775
|
+
|
|
774
776
|
if(parentFore){
|
|
775
777
|
const shared = parentFore.getModel().instances.filter(shared => shared.hasAttribute('shared'));
|
|
776
778
|
if(shared.length !==0) return;
|
|
@@ -888,7 +890,7 @@ export class FxFore extends HTMLElement {
|
|
|
888
890
|
*/
|
|
889
891
|
async _initUI() {
|
|
890
892
|
// console.log('### _initUI()');
|
|
891
|
-
console.log(
|
|
893
|
+
console.log(`### <<<<< _initUI '${this.id}' >>>>>`);
|
|
892
894
|
|
|
893
895
|
if (!this.initialRun) return;
|
|
894
896
|
this.classList.add('initialRun');
|
|
@@ -986,8 +988,9 @@ export class FxFore extends HTMLElement {
|
|
|
986
988
|
if(e.detail.expr){
|
|
987
989
|
console.error('Failing expression',e.detail.expr);
|
|
988
990
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
+
if(this.strict){
|
|
992
|
+
this._displayError(e);
|
|
993
|
+
}
|
|
991
994
|
}
|
|
992
995
|
|
|
993
996
|
_copyToClipboard(target){
|
package/src/fx-instance.js
CHANGED
|
@@ -110,6 +110,7 @@ export class FxInstance extends HTMLElement {
|
|
|
110
110
|
async init() {
|
|
111
111
|
// console.log('fx-instance init');
|
|
112
112
|
await this._initInstance();
|
|
113
|
+
console.log(`### <<<<< instance ${this.id} loaded >>>>> `);
|
|
113
114
|
this.dispatchEvent(
|
|
114
115
|
new CustomEvent('instance-loaded', {
|
|
115
116
|
composed: true,
|
package/src/fx-model.js
CHANGED
|
@@ -106,7 +106,7 @@ export class FxModel extends HTMLElement {
|
|
|
106
106
|
*
|
|
107
107
|
*/
|
|
108
108
|
async modelConstruct() {
|
|
109
|
-
console.log(
|
|
109
|
+
console.log(`### <<<<< dispatching model-construct for '${this.fore.id}' >>>>>`);
|
|
110
110
|
// this.dispatchEvent(new CustomEvent('model-construct', { detail: this }));
|
|
111
111
|
Fore.dispatch(this, 'model-construct', {model: this});
|
|
112
112
|
|
|
@@ -129,7 +129,7 @@ export class FxModel extends HTMLElement {
|
|
|
129
129
|
this.updateModel();
|
|
130
130
|
} else {
|
|
131
131
|
// ### if there's no instance one will created
|
|
132
|
-
console.log(
|
|
132
|
+
console.log(`### <<<<< dispatching model-construct-done for '${this.fore.id}' >>>>>`);
|
|
133
133
|
await this.dispatchEvent(
|
|
134
134
|
new CustomEvent('model-construct-done', {
|
|
135
135
|
composed: false,
|
|
@@ -167,7 +167,7 @@ export class FxModel extends HTMLElement {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
rebuild() {
|
|
170
|
-
console.log(
|
|
170
|
+
console.log(`### <<<<< rebuild() '${this.fore.id}' >>>>>`);
|
|
171
171
|
|
|
172
172
|
this.mainGraph = new DepGraph(false); // do: should be moved down below binds.length check but causes errors in tests.
|
|
173
173
|
this.modelItems = [];
|
|
@@ -203,7 +203,7 @@ export class FxModel extends HTMLElement {
|
|
|
203
203
|
return;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
console.log(
|
|
206
|
+
console.log(`### <<<<< recalculate() '${this.fore.id}' >>>>>`);
|
|
207
207
|
|
|
208
208
|
// console.log('changed nodes ', this.changed);
|
|
209
209
|
this.computes = 0;
|
|
@@ -368,7 +368,7 @@ export class FxModel extends HTMLElement {
|
|
|
368
368
|
|
|
369
369
|
if (this.modelItems.length === 0) return true;
|
|
370
370
|
|
|
371
|
-
console.log(
|
|
371
|
+
console.log(`### <<<<< revalidate() '${this.fore.id}' >>>>>`);
|
|
372
372
|
|
|
373
373
|
// reset submission validation
|
|
374
374
|
// this.parentNode.classList.remove('submit-validation-failed')
|
|
@@ -459,18 +459,40 @@ export class FxModel extends HTMLElement {
|
|
|
459
459
|
// console.log('instances ', this.instances);
|
|
460
460
|
// console.log('instances array ',Array.from(this.instances));
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
|
|
462
|
+
let found;
|
|
463
|
+
if(id === 'default'){
|
|
464
|
+
found = this.getDefaultInstance();
|
|
465
|
+
}
|
|
466
|
+
// ### lookup in local instances first
|
|
464
467
|
if(!found) {
|
|
465
|
-
|
|
468
|
+
const instArray = Array.from(this.instances);
|
|
469
|
+
found = instArray.find(inst => inst.id === id);
|
|
470
|
+
const parentFore = this.fore.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE
|
|
471
|
+
? this.fore.parentNode.host.closest('fx-fore')
|
|
472
|
+
: this.fore.parentNode.closest('fx-fore');
|
|
473
|
+
|
|
474
|
+
}
|
|
475
|
+
// ### lookup in parent Fore if present
|
|
476
|
+
if(!found){
|
|
477
|
+
// const parentFore = this.fore.parentNode.closest('fx-fore');
|
|
478
|
+
const parentFore = this.fore.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE
|
|
479
|
+
? this.fore.parentNode.host.closest('fx-fore')
|
|
480
|
+
: this.fore.parentNode.closest('fx-fore');
|
|
466
481
|
if (parentFore) {
|
|
467
482
|
console.log('shared instances from parent', this.parentNode.id);
|
|
468
483
|
const parentInstances = parentFore.getModel().instances;
|
|
469
484
|
const shared = parentInstances.filter(shared => shared.hasAttribute('shared'));
|
|
470
485
|
found = shared.find(found => found.id === id);
|
|
471
486
|
}
|
|
487
|
+
|
|
472
488
|
}
|
|
473
|
-
if(
|
|
489
|
+
if(found){
|
|
490
|
+
return found;
|
|
491
|
+
}
|
|
492
|
+
if (id === 'default') {
|
|
493
|
+
return this.getDefaultInstance(); // if id is not found always defaults to first in doc order
|
|
494
|
+
}
|
|
495
|
+
if(!found && this.fore.strict){
|
|
474
496
|
// return this.getDefaultInstance(); // if id is not found always defaults to first in doc order
|
|
475
497
|
Fore.dispatch(this, 'error', {
|
|
476
498
|
origin: this,
|
|
@@ -478,7 +500,7 @@ export class FxModel extends HTMLElement {
|
|
|
478
500
|
level:'Error'
|
|
479
501
|
});
|
|
480
502
|
}
|
|
481
|
-
return
|
|
503
|
+
return null;
|
|
482
504
|
}
|
|
483
505
|
|
|
484
506
|
evalBinding(bindingExpr) {
|
package/src/fx-submission.js
CHANGED
|
@@ -85,7 +85,7 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
85
85
|
|
|
86
86
|
model.recalculate();
|
|
87
87
|
|
|
88
|
-
if (this.validate === 'true') {
|
|
88
|
+
if (this.validate === 'true' && this.method !== 'get') {
|
|
89
89
|
const valid = model.revalidate();
|
|
90
90
|
if (!valid) {
|
|
91
91
|
console.log('validation failed. Submission stopped');
|
package/src/getInScopeContext.js
CHANGED
|
@@ -61,10 +61,6 @@ export default function getInScopeContext(node, ref) {
|
|
|
61
61
|
const parentElement = _getElement(node);
|
|
62
62
|
// console.log('getInScopeContext parent', parentElement);
|
|
63
63
|
|
|
64
|
-
if(parentElement.closest('fx-fore').mergePartial){
|
|
65
|
-
console.log('mergePartial mode')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
64
|
if(parentElement.nodeName === 'FX-FORE'){
|
|
69
65
|
return parentElement.getModel().getDefaultInstance().getDefaultContext();
|
|
70
66
|
}
|
package/src/ui/fx-case.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// import { foreElementMixin } from '../ForeElementMixin';
|
|
2
2
|
|
|
3
|
+
import {FxContainer} from "./fx-container.js";
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* `fx-case`
|
|
5
7
|
* a container allowing to switch between fx-case elements
|
|
@@ -7,11 +9,12 @@
|
|
|
7
9
|
* * todo: implement
|
|
8
10
|
* @customElement
|
|
9
11
|
*/
|
|
10
|
-
class FxCase extends
|
|
12
|
+
class FxCase extends FxContainer {
|
|
13
|
+
/*
|
|
11
14
|
constructor() {
|
|
12
15
|
super();
|
|
13
|
-
this.attachShadow({ mode: 'open' });
|
|
14
16
|
}
|
|
17
|
+
*/
|
|
15
18
|
|
|
16
19
|
connectedCallback() {
|
|
17
20
|
if (this.hasAttribute('label')) {
|