@jinntec/fore 1.4.0 → 1.6.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 -36
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +2 -30
- package/dist/fore.js.map +1 -1
- package/index.js +13 -0
- package/package.json +9 -5
- package/resources/fore.css +178 -92
- package/src/DependencyNotifyingDomFacade.js +1 -2
- package/src/ForeElementMixin.js +31 -5
- package/src/actions/abstract-action.js +379 -270
- package/src/actions/fx-action.js +0 -1
- package/src/actions/fx-append.js +1 -2
- package/src/actions/fx-confirm.js +12 -0
- package/src/actions/fx-copy.js +0 -1
- package/src/actions/fx-delete.js +31 -9
- package/src/actions/fx-dispatch.js +19 -5
- package/src/actions/fx-hide.js +19 -0
- package/src/actions/fx-insert.js +72 -8
- package/src/actions/fx-load.js +253 -0
- package/src/actions/fx-message.js +22 -7
- package/src/actions/fx-refresh.js +11 -1
- package/src/actions/fx-reload.js +12 -2
- package/src/actions/fx-replace.js +5 -4
- package/src/actions/fx-reset.js +48 -0
- package/src/actions/fx-return.js +0 -1
- package/src/actions/fx-send.js +40 -2
- package/src/actions/fx-setfocus.js +25 -7
- package/src/actions/fx-setvalue.js +32 -4
- package/src/actions/fx-show.js +14 -2
- package/src/actions/fx-toggle.js +0 -1
- package/src/actions/fx-update.js +9 -0
- package/src/events.js +0 -1
- package/src/fore.js +119 -63
- package/src/functions/common-function.js +28 -0
- package/src/fx-bind.js +7 -7
- package/src/fx-fore.js +207 -54
- package/src/fx-instance.js +55 -17
- package/src/fx-model.js +31 -33
- package/src/fx-submission.js +50 -47
- package/src/getInScopeContext.js +22 -8
- package/src/lab/fore-component.js +90 -0
- package/src/lab/instance-inspector.js +56 -0
- package/src/lab/template.html +16 -0
- package/src/relevance.js +27 -1
- package/src/tools/adi.js +1056 -0
- package/src/tools/fx-action-log.js +662 -0
- package/src/tools/fx-devtools.js +444 -0
- package/src/tools/fx-dom-inspector.js +609 -0
- package/src/tools/fx-json-instance.js +435 -0
- package/src/tools/fx-log-item.js +133 -0
- package/src/tools/fx-log-settings.js +474 -0
- package/src/tools/fx-minimap.js +194 -0
- package/src/tools/helpers.js +132 -0
- package/src/ui/abstract-control.js +41 -3
- package/src/ui/fx-action-log.js +358 -0
- package/src/ui/fx-alert.js +0 -1
- package/src/ui/fx-container.js +14 -3
- package/src/ui/fx-control.js +553 -474
- package/src/ui/fx-dialog.js +2 -0
- package/src/ui/fx-dom-inspector.js +1255 -0
- package/src/ui/fx-group.js +3 -4
- package/src/ui/fx-hint.js +2 -4
- package/src/ui/fx-inspector.js +5 -6
- package/src/ui/fx-items.js +55 -14
- package/src/ui/fx-output.js +36 -17
- package/src/ui/fx-repeat-attributes.js +409 -0
- package/src/ui/fx-repeat.js +12 -6
- package/src/ui/fx-switch.js +14 -3
- package/src/ui/fx-trigger.js +13 -1
- package/src/xpath-evaluation.js +109 -26
- package/src/xpath-util.js +55 -1
package/src/fx-fore.js
CHANGED
|
@@ -2,9 +2,10 @@ import {Fore} from './fore.js';
|
|
|
2
2
|
import './fx-instance.js';
|
|
3
3
|
import {FxModel} from './fx-model.js';
|
|
4
4
|
import '@jinntec/jinn-toast';
|
|
5
|
-
import {evaluateXPathToBoolean, evaluateXPathToNodes, evaluateXPathToString} from './xpath-evaluation.js';
|
|
5
|
+
import {evaluateXPathToBoolean, evaluateXPathToNodes, evaluateXPathToFirstNode, evaluateXPathToString} from './xpath-evaluation.js';
|
|
6
6
|
import getInScopeContext from './getInScopeContext.js';
|
|
7
7
|
import {XPathUtil} from './xpath-util.js';
|
|
8
|
+
import {FxRepeatAttributes} from './ui/fx-repeat-attributes.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Main class for Fore.Outermost container element for each Fore application.
|
|
@@ -24,6 +25,8 @@ import {XPathUtil} from './xpath-util.js';
|
|
|
24
25
|
* @ts-check
|
|
25
26
|
*/
|
|
26
27
|
export class FxFore extends HTMLElement {
|
|
28
|
+
static outermostHandler = null;
|
|
29
|
+
|
|
27
30
|
static get properties() {
|
|
28
31
|
return {
|
|
29
32
|
/**
|
|
@@ -41,6 +44,12 @@ export class FxFore extends HTMLElement {
|
|
|
41
44
|
ready: {
|
|
42
45
|
type: Boolean,
|
|
43
46
|
},
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
validateOn: {
|
|
51
|
+
type: String
|
|
52
|
+
}
|
|
44
53
|
};
|
|
45
54
|
}
|
|
46
55
|
|
|
@@ -55,9 +64,13 @@ export class FxFore extends HTMLElement {
|
|
|
55
64
|
constructor() {
|
|
56
65
|
super();
|
|
57
66
|
this.model = {};
|
|
67
|
+
this.inited=false;
|
|
58
68
|
// this.addEventListener('model-construct-done', this._handleModelConstructDone);
|
|
69
|
+
// todo: refactoring - these should rather go into connectedcallback
|
|
59
70
|
this.addEventListener('message', this._displayMessage);
|
|
60
71
|
this.addEventListener('error', this._displayError);
|
|
72
|
+
this.addEventListener('warn', this._displayWarning);
|
|
73
|
+
this.addEventListener('log', this._logError);
|
|
61
74
|
window.addEventListener('compute-exception', e => {
|
|
62
75
|
console.error('circular dependency: ', e);
|
|
63
76
|
});
|
|
@@ -65,6 +78,10 @@ export class FxFore extends HTMLElement {
|
|
|
65
78
|
this.ready = false;
|
|
66
79
|
this.storedTemplateExpressionByNode = new Map();
|
|
67
80
|
|
|
81
|
+
// Stores the outer most action handler. If an action handler is already running, all
|
|
82
|
+
// updates are included in that one
|
|
83
|
+
this.outermostHandler = null;
|
|
84
|
+
|
|
68
85
|
const style = `
|
|
69
86
|
:host {
|
|
70
87
|
display: block;
|
|
@@ -135,13 +152,20 @@ export class FxFore extends HTMLElement {
|
|
|
135
152
|
#messageContent{
|
|
136
153
|
margin-top:40px;
|
|
137
154
|
}
|
|
155
|
+
.warning{
|
|
156
|
+
background:orange;
|
|
157
|
+
}
|
|
138
158
|
`;
|
|
139
159
|
|
|
140
160
|
const html = `
|
|
161
|
+
<noscript>This page uses Web Components and needs JavaScript to be enabled..</noscript>
|
|
162
|
+
|
|
141
163
|
<jinn-toast id="message" gravity="bottom" position="left"></jinn-toast>
|
|
142
164
|
<jinn-toast id="sticky" gravity="bottom" position="left" duration="-1" close="true" data-class="sticky-message"></jinn-toast>
|
|
143
|
-
<jinn-toast id="error" text="error" duration="-1" data-class="error" close="true" position="left" gravity="bottom"></jinn-toast>
|
|
144
|
-
<
|
|
165
|
+
<jinn-toast id="error" text="error" duration="-1" data-class="error" close="true" position="left" gravity="bottom" escape-markup="false"></jinn-toast>
|
|
166
|
+
<jinn-toast id="warn" text="warning" duration="-1" data-class="warning" close="true" position="right" gravity="bottom"></jinn-toast>
|
|
167
|
+
<slot id="default"></slot>
|
|
168
|
+
<slot name="messages"></slot>
|
|
145
169
|
<div id="modalMessage" class="overlay">
|
|
146
170
|
<div class="popup">
|
|
147
171
|
<h2></h2>
|
|
@@ -149,6 +173,7 @@ export class FxFore extends HTMLElement {
|
|
|
149
173
|
<div id="messageContent"></div>
|
|
150
174
|
</div>
|
|
151
175
|
</div>
|
|
176
|
+
<slot name="event"></slot>
|
|
152
177
|
`;
|
|
153
178
|
|
|
154
179
|
this.attachShadow({mode: 'open'});
|
|
@@ -162,6 +187,8 @@ export class FxFore extends HTMLElement {
|
|
|
162
187
|
this.toRefresh = [];
|
|
163
188
|
this.initialRun = true;
|
|
164
189
|
this.someInstanceDataStructureChanged = false;
|
|
190
|
+
this.repeatsFromAttributesCreated = false;
|
|
191
|
+
this.validateOn = this.hasAttribute('validate-on') ? this.getAttribute('validate-on'):'update';
|
|
165
192
|
}
|
|
166
193
|
|
|
167
194
|
connectedCallback() {
|
|
@@ -202,10 +229,12 @@ export class FxFore extends HTMLElement {
|
|
|
202
229
|
return;
|
|
203
230
|
}
|
|
204
231
|
|
|
205
|
-
|
|
206
|
-
slot.addEventListener('slotchange', async event => {
|
|
232
|
+
this._injectDevtools();
|
|
207
233
|
|
|
234
|
+
const slot = this.shadowRoot.querySelector('slot#default');
|
|
235
|
+
slot.addEventListener('slotchange', async event => {
|
|
208
236
|
// preliminary addition for auto-conversion of non-prefixed element into prefixed elements. See fore.js
|
|
237
|
+
if(this.inited) return;
|
|
209
238
|
if(this.hasAttribute('convert')){
|
|
210
239
|
this.replaceWith(Fore.copyDom(this));
|
|
211
240
|
// Fore.copyDom(this);
|
|
@@ -220,6 +249,9 @@ export class FxFore extends HTMLElement {
|
|
|
220
249
|
const generatedModel = document.createElement('fx-model');
|
|
221
250
|
this.appendChild(generatedModel);
|
|
222
251
|
modelElement = generatedModel;
|
|
252
|
+
// We are going to get a new slotchange event immediately, because we changed a slot.
|
|
253
|
+
// so cancel this one.
|
|
254
|
+
return;
|
|
223
255
|
}
|
|
224
256
|
if (!modelElement.inited) {
|
|
225
257
|
console.info(
|
|
@@ -227,20 +259,33 @@ export class FxFore extends HTMLElement {
|
|
|
227
259
|
"background:#64b5f6; color:white; padding:1rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;",
|
|
228
260
|
);
|
|
229
261
|
|
|
230
|
-
if (this.src) {
|
|
231
|
-
console.log('########## FORE: loaded from ... ', this.src, '##########');
|
|
232
|
-
}
|
|
233
262
|
await modelElement.modelConstruct();
|
|
234
263
|
this._handleModelConstructDone();
|
|
235
264
|
}
|
|
236
265
|
this.model = modelElement;
|
|
266
|
+
|
|
267
|
+
this._createRepeatsFromAttributes();
|
|
268
|
+
this.inited = true;
|
|
269
|
+
|
|
237
270
|
});
|
|
238
271
|
this.addEventListener('path-mutated', () => {
|
|
239
|
-
// console.log('path-mutated event received', e.detail.path, e.detail.index);
|
|
240
272
|
this.someInstanceDataStructureChanged = true;
|
|
241
273
|
});
|
|
242
274
|
}
|
|
243
275
|
|
|
276
|
+
_injectDevtools(){
|
|
277
|
+
if (this.ownerDocument.querySelector('fx-devtools')) {
|
|
278
|
+
// There's already a devtools, so we can ignore this one.
|
|
279
|
+
// One devtools can focus multiple fore elements
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const search = window.location.search;
|
|
283
|
+
const urlParams = new URLSearchParams(search);
|
|
284
|
+
if(urlParams.has('inspect')){
|
|
285
|
+
const devtools = document.createElement('fx-devtools');
|
|
286
|
+
document.body.appendChild(devtools);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
244
289
|
addToRefresh(modelItem) {
|
|
245
290
|
const found = this.toRefresh.find(mi => mi.path === modelItem.path);
|
|
246
291
|
if (!found) {
|
|
@@ -255,7 +300,7 @@ export class FxFore extends HTMLElement {
|
|
|
255
300
|
* @private
|
|
256
301
|
*/
|
|
257
302
|
_loadFromSrc() {
|
|
258
|
-
console.log('########## loading Fore from ', this.src, '##########');
|
|
303
|
+
// console.log('########## loading Fore from ', this.src, '##########');
|
|
259
304
|
fetch(this.src, {
|
|
260
305
|
method: 'GET',
|
|
261
306
|
mode: 'cors',
|
|
@@ -291,6 +336,12 @@ export class FxFore extends HTMLElement {
|
|
|
291
336
|
});
|
|
292
337
|
}
|
|
293
338
|
theFore.setAttribute('from-src', this.src);
|
|
339
|
+
const thisAttrs = this.attributes;
|
|
340
|
+
Array.from(thisAttrs).forEach(attr =>{
|
|
341
|
+
if(attr.name !== 'src'){
|
|
342
|
+
theFore.setAttribute(attr.name,attr.value);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
294
345
|
this.replaceWith(theFore);
|
|
295
346
|
})
|
|
296
347
|
.catch(() => {
|
|
@@ -307,7 +358,7 @@ export class FxFore extends HTMLElement {
|
|
|
307
358
|
* @param observer
|
|
308
359
|
*/
|
|
309
360
|
handleIntersect(entries, observer) {
|
|
310
|
-
console.time('refreshLazy');
|
|
361
|
+
// console.time('refreshLazy');
|
|
311
362
|
|
|
312
363
|
entries.forEach(entry => {
|
|
313
364
|
const {target} = entry;
|
|
@@ -316,7 +367,7 @@ export class FxFore extends HTMLElement {
|
|
|
316
367
|
if(fore.initialRun) return;
|
|
317
368
|
|
|
318
369
|
if (entry.isIntersecting) {
|
|
319
|
-
console.log('in view', entry);
|
|
370
|
+
// console.log('in view', entry);
|
|
320
371
|
// console.log('repeat in view entry', entry.target);
|
|
321
372
|
// const target = entry.target;
|
|
322
373
|
// if(target.hasAttribute('refresh-on-view')){
|
|
@@ -325,17 +376,17 @@ export class FxFore extends HTMLElement {
|
|
|
325
376
|
|
|
326
377
|
// todo: too restrictive here? what if target is a usual html element? shouldn't it refresh downwards?
|
|
327
378
|
if (typeof target.refresh === 'function') {
|
|
328
|
-
console.log('refreshing target', target);
|
|
379
|
+
// console.log('refreshing target', target);
|
|
329
380
|
target.refresh(target, true);
|
|
330
381
|
} else {
|
|
331
|
-
console.log('refreshing children', target);
|
|
382
|
+
// console.log('refreshing children', target);
|
|
332
383
|
Fore.refreshChildren(target, true);
|
|
333
384
|
}
|
|
334
385
|
}
|
|
335
386
|
});
|
|
336
387
|
entries[0].target.getOwnerForm().dispatchEvent(new CustomEvent('refresh-done'));
|
|
337
388
|
|
|
338
|
-
console.timeEnd('refreshLazy');
|
|
389
|
+
// console.timeEnd('refreshLazy');
|
|
339
390
|
}
|
|
340
391
|
|
|
341
392
|
evaluateToNodes(xpath, context) {
|
|
@@ -361,8 +412,8 @@ export class FxFore extends HTMLElement {
|
|
|
361
412
|
*
|
|
362
413
|
*/
|
|
363
414
|
async forceRefresh() {
|
|
364
|
-
console.time('refresh');
|
|
365
|
-
console.group('### forced refresh', this);
|
|
415
|
+
// console.time('refresh');
|
|
416
|
+
// console.group('### forced refresh', this);
|
|
366
417
|
|
|
367
418
|
Fore.refreshChildren(this, true);
|
|
368
419
|
this._updateTemplateExpressions();
|
|
@@ -370,23 +421,16 @@ export class FxFore extends HTMLElement {
|
|
|
370
421
|
this._processTemplateExpressions();
|
|
371
422
|
Fore.dispatch(this, 'refresh-done', {});
|
|
372
423
|
|
|
373
|
-
console.groupEnd();
|
|
374
|
-
console.timeEnd('refresh');
|
|
424
|
+
// console.groupEnd();
|
|
425
|
+
// console.timeEnd('refresh');
|
|
375
426
|
}
|
|
376
427
|
|
|
377
428
|
async refresh(force) {
|
|
378
429
|
// refresh () {
|
|
379
|
-
console.info('%crefresh','font-style: italic; background: #8bc34a; color:white; padding:0.3rem 5rem 0.3rem 0.3rem; display:block; width:100%;');
|
|
380
|
-
console.group('refresh', force);
|
|
381
|
-
|
|
382
|
-
console.time('refresh');
|
|
383
|
-
|
|
384
430
|
// ### refresh Fore UI elements
|
|
385
|
-
// console.time('refreshChildren');
|
|
386
|
-
console.log('toRefresh', this.toRefresh);
|
|
387
|
-
|
|
388
431
|
// if (!this.initialRun && this.toRefresh.length !== 0) {
|
|
389
432
|
if (!force && !this.initialRun && this.toRefresh.length !== 0) {
|
|
433
|
+
// console.log('toRefresh', this.toRefresh);
|
|
390
434
|
let needsRefresh = false;
|
|
391
435
|
|
|
392
436
|
// ### after recalculation the changed modelItems are copied to 'toRefresh' array for processing
|
|
@@ -419,10 +463,20 @@ export class FxFore extends HTMLElement {
|
|
|
419
463
|
}
|
|
420
464
|
});
|
|
421
465
|
this.toRefresh = [];
|
|
466
|
+
/*
|
|
422
467
|
if (!needsRefresh) {
|
|
423
468
|
console.log('no dependants to refresh');
|
|
424
469
|
}
|
|
470
|
+
*/
|
|
425
471
|
} else {
|
|
472
|
+
// ### resetting visited state for controls to refresh
|
|
473
|
+
/*
|
|
474
|
+
const visited = this.parentNode.querySelectorAll('.visited');
|
|
475
|
+
Array.from(visited).forEach(v =>{
|
|
476
|
+
v.classList.remove('visited');
|
|
477
|
+
});
|
|
478
|
+
*/
|
|
479
|
+
|
|
426
480
|
Fore.refreshChildren(this, true);
|
|
427
481
|
// console.timeEnd('refreshChildren');
|
|
428
482
|
}
|
|
@@ -434,9 +488,6 @@ export class FxFore extends HTMLElement {
|
|
|
434
488
|
}
|
|
435
489
|
this._processTemplateExpressions();
|
|
436
490
|
|
|
437
|
-
console.timeEnd('refresh');
|
|
438
|
-
|
|
439
|
-
console.groupEnd();
|
|
440
491
|
// console.log('### <<<<< dispatching refresh-done - end of UI update cycle >>>>>');
|
|
441
492
|
// this.dispatchEvent(new CustomEvent('refresh-done'));
|
|
442
493
|
// this.initialRun = false;
|
|
@@ -488,12 +539,12 @@ export class FxFore extends HTMLElement {
|
|
|
488
539
|
for (const node of Array.from(this.storedTemplateExpressionByNode.keys())) {
|
|
489
540
|
if (node.nodeType === Node.ATTRIBUTE_NODE) {
|
|
490
541
|
// Attribute nodes are not contained by the document, but their owner elements are!
|
|
491
|
-
if (!
|
|
542
|
+
if (!XPathUtil.contains(this, node.ownerElement)) {
|
|
492
543
|
this.storedTemplateExpressionByNode.delete(node);
|
|
493
544
|
continue;
|
|
494
545
|
}
|
|
495
|
-
} else if (!
|
|
496
|
-
// For all other nodes, if
|
|
546
|
+
} else if (!XPathUtil.contains(this, node)) {
|
|
547
|
+
// For all other nodes, if this `fore` element does not contain them, they are dead
|
|
497
548
|
this.storedTemplateExpressionByNode.delete(node);
|
|
498
549
|
continue;
|
|
499
550
|
}
|
|
@@ -515,10 +566,9 @@ export class FxFore extends HTMLElement {
|
|
|
515
566
|
}
|
|
516
567
|
|
|
517
568
|
/**
|
|
518
|
-
* evaluate a template expression
|
|
519
|
-
* @param
|
|
569
|
+
* evaluate a template expression on a node either text- or attribute node.
|
|
570
|
+
* @param expr The string to parse for expressions
|
|
520
571
|
* @param node the node which will get updated with evaluation result
|
|
521
|
-
* @param form the form element
|
|
522
572
|
*/
|
|
523
573
|
evaluateTemplateExpression(expr, node) {
|
|
524
574
|
const replaced = expr.replace(/{[^}]*}/g, match => {
|
|
@@ -536,11 +586,15 @@ export class FxFore extends HTMLElement {
|
|
|
536
586
|
// Templates are special: they use the namespace configuration from the place where they are
|
|
537
587
|
// being defined
|
|
538
588
|
const instanceId = XPathUtil.getInstanceId(naked);
|
|
539
|
-
|
|
540
|
-
|
|
589
|
+
|
|
590
|
+
// If there is an instance referred
|
|
591
|
+
const inst = instanceId ? this.getModel().getInstance(instanceId) : this.getModel().getDefaultInstance();
|
|
592
|
+
|
|
593
|
+
try {
|
|
541
594
|
return evaluateXPathToString(naked, inscope, node, null, inst);
|
|
542
595
|
} catch (error) {
|
|
543
|
-
console.
|
|
596
|
+
console.warn('ignoring unparseable expr', error);
|
|
597
|
+
|
|
544
598
|
return match;
|
|
545
599
|
}
|
|
546
600
|
});
|
|
@@ -584,21 +638,17 @@ export class FxFore extends HTMLElement {
|
|
|
584
638
|
window.addEventListener('beforeunload', event => {
|
|
585
639
|
const mustDisplay = evaluateXPathToBoolean(condition, this.getModel().getDefaultContext(), this)
|
|
586
640
|
if(mustDisplay){
|
|
587
|
-
console.log('have to display confirmation')
|
|
588
641
|
return event.returnValue = 'are you sure';
|
|
589
642
|
}
|
|
590
643
|
event.preventDefault();
|
|
591
|
-
console.log('do not display confirmation')
|
|
592
644
|
})
|
|
593
645
|
}else{
|
|
594
646
|
window.addEventListener('beforeunload', event => {
|
|
595
647
|
// if(AbstractAction.dataChanged){
|
|
596
648
|
if(FxModel.dataChanged){
|
|
597
|
-
console.log('have to display confirmation')
|
|
598
649
|
return event.returnValue = 'are you sure';
|
|
599
650
|
}
|
|
600
651
|
event.preventDefault();
|
|
601
|
-
console.log('do not display confirmation')
|
|
602
652
|
})
|
|
603
653
|
}
|
|
604
654
|
}
|
|
@@ -616,7 +666,7 @@ export class FxFore extends HTMLElement {
|
|
|
616
666
|
async _lazyCreateInstance() {
|
|
617
667
|
const model = this.querySelector('fx-model');
|
|
618
668
|
if (model.instances.length === 0) {
|
|
619
|
-
console.log('### lazy creation of instance');
|
|
669
|
+
// console.log('### lazy creation of instance');
|
|
620
670
|
const generatedInstance = document.createElement('fx-instance');
|
|
621
671
|
model.appendChild(generatedInstance);
|
|
622
672
|
|
|
@@ -625,7 +675,7 @@ export class FxFore extends HTMLElement {
|
|
|
625
675
|
this._generateInstance(this, generated.firstElementChild);
|
|
626
676
|
generatedInstance.instanceData = generated;
|
|
627
677
|
model.instances.push(generatedInstance);
|
|
628
|
-
console.log('generatedInstance ', this.getModel().getDefaultInstanceData());
|
|
678
|
+
// console.log('generatedInstance ', this.getModel().getDefaultInstanceData());
|
|
629
679
|
}
|
|
630
680
|
}
|
|
631
681
|
|
|
@@ -638,11 +688,9 @@ export class FxFore extends HTMLElement {
|
|
|
638
688
|
const ref = start.getAttribute('ref');
|
|
639
689
|
|
|
640
690
|
if (ref.includes('/')) {
|
|
641
|
-
console.log('complex path to create ', ref);
|
|
691
|
+
// console.log('complex path to create ', ref);
|
|
642
692
|
const steps = ref.split('/');
|
|
643
693
|
steps.forEach(step => {
|
|
644
|
-
console.log('step ', step);
|
|
645
|
-
|
|
646
694
|
// const generated = document.createElement(ref);
|
|
647
695
|
parent = this._generateNode(parent, step, start);
|
|
648
696
|
});
|
|
@@ -722,8 +770,9 @@ export class FxFore extends HTMLElement {
|
|
|
722
770
|
* @private
|
|
723
771
|
*/
|
|
724
772
|
async _initUI() {
|
|
725
|
-
console.log('### _initUI()');
|
|
773
|
+
// console.log('### _initUI()');
|
|
726
774
|
if (!this.initialRun) return;
|
|
775
|
+
this.classList.add('initialRun');
|
|
727
776
|
await this._lazyCreateInstance();
|
|
728
777
|
|
|
729
778
|
// console.log('registering variables!');
|
|
@@ -757,12 +806,8 @@ export class FxFore extends HTMLElement {
|
|
|
757
806
|
// console.log('### >>>>> dispatching ready >>>>>', this);
|
|
758
807
|
// console.log('### modelItems: ', this.getModel().modelItems);
|
|
759
808
|
Fore.dispatch(this, 'ready', {});
|
|
760
|
-
console.
|
|
761
|
-
`%cPage Initialization done`,
|
|
762
|
-
"background:#64b5f6; color:white; padding:1rem; display:block; white-space: nowrap; border-radius:0.3rem;width:100%;",
|
|
763
|
-
);
|
|
809
|
+
// console.log('dataChanged', FxModel.dataChanged);
|
|
764
810
|
console.timeEnd('init');
|
|
765
|
-
console.log('dataChanged', FxModel.dataChanged);
|
|
766
811
|
}
|
|
767
812
|
|
|
768
813
|
registerLazyElement(element) {
|
|
@@ -802,6 +847,50 @@ export class FxFore extends HTMLElement {
|
|
|
802
847
|
toast.showToast(msg);
|
|
803
848
|
}
|
|
804
849
|
|
|
850
|
+
_displayWarning(e){
|
|
851
|
+
const msg = e.detail.message;
|
|
852
|
+
// this._showMessage('modal', msg);
|
|
853
|
+
const path = XPathUtil.shortenPath(evaluateXPathToString('path()',e.target,this));
|
|
854
|
+
const toast = this.shadowRoot.querySelector('#warn');
|
|
855
|
+
toast.showToast(`WARN: ${path}:${msg}`);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
_logError(e) {
|
|
859
|
+
e.stopPropagation();
|
|
860
|
+
e.preventDefault();
|
|
861
|
+
|
|
862
|
+
const div = document.createElement('div');
|
|
863
|
+
div.setAttribute('slot','messages');
|
|
864
|
+
div.setAttribute('data-level',e.detail.level);
|
|
865
|
+
|
|
866
|
+
const id = document.createElement('div');
|
|
867
|
+
id.textContent = `"${e.detail.id}"`;
|
|
868
|
+
div.appendChild(id);
|
|
869
|
+
|
|
870
|
+
const path = document.createElement('div');
|
|
871
|
+
const pathExpr = XPathUtil.shortenPath(evaluateXPathToString('path()',e.target,this));
|
|
872
|
+
// console.log('pathExpr',pathExpr)
|
|
873
|
+
path.textContent = pathExpr;
|
|
874
|
+
div.appendChild(path);
|
|
875
|
+
|
|
876
|
+
const message = document.createElement('div');
|
|
877
|
+
message.textContent = e.detail.message;
|
|
878
|
+
div.appendChild(message);
|
|
879
|
+
|
|
880
|
+
/*
|
|
881
|
+
const path = XPathUtil.shortenPath(evaluateXPathToString('path()',e.target,this));
|
|
882
|
+
div.innerText = `${path} :: ${e.detail.message}`;
|
|
883
|
+
*/
|
|
884
|
+
this.appendChild(div);
|
|
885
|
+
div.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
const errorElement = evaluateXPathToFirstNode(`/${pathExpr}`,document,null);
|
|
889
|
+
errorElement.classList.add('fore-error');
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
}
|
|
893
|
+
|
|
805
894
|
_showMessage(level, msg) {
|
|
806
895
|
if (level === 'modal') {
|
|
807
896
|
// this.$.messageContent.innerText = msg;
|
|
@@ -818,6 +907,70 @@ export class FxFore extends HTMLElement {
|
|
|
818
907
|
toast.showToast(msg);
|
|
819
908
|
}
|
|
820
909
|
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* wraps the element having a 'data-ref' attribute with an fx-repeat-attributes element.
|
|
913
|
+
* @private
|
|
914
|
+
*/
|
|
915
|
+
_createRepeatsFromAttributes() {
|
|
916
|
+
if(this.repeatsFromAttributesCreated) return;
|
|
917
|
+
const repeats = this.querySelectorAll('[data-ref]');
|
|
918
|
+
if(repeats){
|
|
919
|
+
Array.from(repeats).forEach(item =>{
|
|
920
|
+
if(item.closest('fx-control')) return;
|
|
921
|
+
/*
|
|
922
|
+
const parentRepeat = item.closest('fx-repeat');
|
|
923
|
+
if(parentRepeat){
|
|
924
|
+
this.dispatchEvent(
|
|
925
|
+
new CustomEvent('log', {
|
|
926
|
+
composed: false,
|
|
927
|
+
bubbles: true,
|
|
928
|
+
cancelable:true,
|
|
929
|
+
detail: { id:this.id, message: `nesting elements with data-ref attributes within fx-repeat is not supported by now`, level:'Error'},
|
|
930
|
+
}),
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
*/
|
|
934
|
+
|
|
935
|
+
const table = item.parentNode.closest('table');
|
|
936
|
+
let host;
|
|
937
|
+
if(table){
|
|
938
|
+
host = table.cloneNode(true);
|
|
939
|
+
}else{
|
|
940
|
+
host = item.cloneNode(true);
|
|
941
|
+
}
|
|
942
|
+
// ### clone original item to move it into fx-repeat-attributes
|
|
943
|
+
// const host = item.cloneNode(true);
|
|
944
|
+
|
|
945
|
+
// ### create wrapper element
|
|
946
|
+
const repeatFromAttr = new FxRepeatAttributes();
|
|
947
|
+
// const repeatFromAttr = document.createElement('fx-repeat-attributes');
|
|
948
|
+
|
|
949
|
+
// ### copy the value of 'data-ref' to 'ref' on fx-repeat-attributes
|
|
950
|
+
repeatFromAttr.setAttribute('ref',item.getAttribute('data-ref'));
|
|
951
|
+
// item.removeAttribute('data-ref');
|
|
952
|
+
|
|
953
|
+
// ### append the cloned original element to fx-repeat-attributes
|
|
954
|
+
repeatFromAttr.appendChild(host);
|
|
955
|
+
|
|
956
|
+
// ### insert fx-repeat-attributes element before element with the 'data-ref'
|
|
957
|
+
// repeats[0].parentNode.insertBefore(repeatFromAttr,repeats[0]);
|
|
958
|
+
|
|
959
|
+
if(table){
|
|
960
|
+
table.parentNode.insertBefore(repeatFromAttr,table);
|
|
961
|
+
table.parentNode.removeChild(table);
|
|
962
|
+
}else{
|
|
963
|
+
item.parentNode.insertBefore(repeatFromAttr,item);
|
|
964
|
+
item.parentNode.removeChild(item);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// ### remove original item from DOM
|
|
968
|
+
item.setAttribute('insertPoint','');
|
|
969
|
+
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
this.repeatsFromAttributesCreated = true;
|
|
973
|
+
}
|
|
821
974
|
}
|
|
822
975
|
|
|
823
976
|
if (!customElements.get('fx-fore')) {
|