@jinntec/fore 1.1.0 → 1.3.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 +8 -8
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +7 -7
- package/dist/fore.js.map +1 -1
- package/index.js +1 -0
- package/package.json +2 -2
- package/resources/fore.css +95 -72
- package/src/ForeElementMixin.js +1 -1
- package/src/actions/abstract-action.js +55 -7
- package/src/actions/fx-action.js +2 -2
- package/src/actions/fx-confirm.js +2 -2
- package/src/actions/fx-delete.js +53 -62
- package/src/actions/fx-hide.js +3 -1
- package/src/actions/fx-message.js +25 -1
- package/src/actions/fx-refresh.js +9 -0
- package/src/actions/fx-reload.js +30 -0
- package/src/actions/fx-replace.js +1 -0
- package/src/actions/fx-send.js +11 -1
- package/src/actions/fx-setfocus.js +32 -5
- package/src/actions/fx-setvalue.js +4 -4
- package/src/actions/fx-show.js +1 -0
- package/src/actions/fx-toggle.js +5 -0
- package/src/events.js +24 -0
- package/src/fore.js +71 -8
- package/src/fx-bind.js +2 -2
- package/src/fx-fore.js +71 -20
- package/src/fx-instance.js +33 -8
- package/src/fx-model.js +435 -444
- package/src/fx-submission.js +78 -65
- package/src/getInScopeContext.js +91 -83
- package/src/modelitem.js +2 -2
- package/src/relevance.js +1 -1
- package/src/ui/abstract-control.js +114 -27
- package/src/ui/fx-alert.js +0 -1
- package/src/ui/fx-container.js +23 -27
- package/src/ui/fx-control.js +90 -34
- package/src/ui/fx-group.js +5 -0
- package/src/ui/fx-inspector.js +5 -2
- package/src/ui/fx-output.js +17 -15
- package/src/ui/fx-repeat.js +2 -2
- package/src/ui/fx-repeatitem.js +5 -3
- package/src/ui/fx-switch.js +11 -7
- package/src/ui/fx-trigger.js +15 -9
- package/src/xpath-evaluation.js +31 -18
- package/src/xpath-util.js +13 -0
package/src/ui/fx-container.js
CHANGED
|
@@ -37,31 +37,30 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
37
37
|
/**
|
|
38
38
|
* (re)apply all state properties to this control.
|
|
39
39
|
*/
|
|
40
|
-
refresh(force) {
|
|
40
|
+
async refresh(force) {
|
|
41
41
|
if (!force && this.hasAttribute('refresh-on-view')) return;
|
|
42
42
|
// console.log('### FxContainer.refresh on : ', this);
|
|
43
43
|
|
|
44
44
|
if (this.isBound()) {
|
|
45
45
|
this.evalInContext();
|
|
46
46
|
this.modelItem = this.getModelItem();
|
|
47
|
-
if (!this.modelItem.boundControls.includes(this)) {
|
|
47
|
+
if (this.modelItem && !this.modelItem.boundControls.includes(this)) {
|
|
48
48
|
this.modelItem.boundControls.push(this);
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
// this.value = this.modelItem.value;
|
|
50
|
+
this.handleModelItemProperties();
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
// await this.updateComplete;
|
|
55
|
-
|
|
56
53
|
// state change event do not fire during init phase (initial refresh)
|
|
57
|
-
if (this._getForm().ready) {
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
Fore.refreshChildren(this, force);
|
|
54
|
+
// if (this._getForm().ready) {
|
|
55
|
+
// this.handleModelItemProperties();
|
|
56
|
+
// }
|
|
57
|
+
// Fore.refreshChildren(this, force);
|
|
61
58
|
}
|
|
62
59
|
|
|
60
|
+
/**
|
|
61
|
+
* anly relevance is processed for container controls
|
|
62
|
+
*/
|
|
63
63
|
handleModelItemProperties() {
|
|
64
|
-
this.handleReadonly();
|
|
65
64
|
this.handleRelevant();
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -69,28 +68,25 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
69
68
|
return this.getModel().parentNode;
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
handleReadonly() {
|
|
73
|
-
// console.log('mip readonly', this.modelItem.isReadonly);
|
|
74
|
-
if (this.isReadonly() !== this.modelItem.readonly) {
|
|
75
|
-
if (this.modelItem.readonly) {
|
|
76
|
-
this.setAttribute('readonly', 'readonly');
|
|
77
|
-
this.dispatchEvent(new CustomEvent('readonly', {}));
|
|
78
|
-
}
|
|
79
|
-
if (!this.modelItem.readonly) {
|
|
80
|
-
this.removeAttribute('readonly');
|
|
81
|
-
this.dispatchEvent(new CustomEvent('readwrite', {}));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
71
|
handleRelevant() {
|
|
87
72
|
// console.log('mip valid', this.modelItem.enabled);
|
|
88
|
-
if (!this.modelItem)
|
|
73
|
+
if (!this.modelItem) {
|
|
74
|
+
console.log('container is not relevant');
|
|
75
|
+
this.removeAttribute('relevant','');
|
|
76
|
+
this.setAttribute('nonrelevant','');
|
|
77
|
+
this.dispatchEvent(new CustomEvent('disabled', {}));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
89
80
|
|
|
90
81
|
if (this.isEnabled() !== this.modelItem.enabled) {
|
|
91
|
-
if (this.modelItem.
|
|
82
|
+
if (this.modelItem.relevant) {
|
|
83
|
+
// this.style.display = 'block';
|
|
84
|
+
this.removeAttribute('nonrelevant','');
|
|
85
|
+
this.setAttribute('relevant','');
|
|
92
86
|
this.dispatchEvent(new CustomEvent('enabled', {}));
|
|
93
87
|
} else {
|
|
88
|
+
this.removeAttribute('relevant','');
|
|
89
|
+
this.setAttribute('nonrelevant','');
|
|
94
90
|
this.dispatchEvent(new CustomEvent('disabled', {}));
|
|
95
91
|
}
|
|
96
92
|
}
|
package/src/ui/fx-control.js
CHANGED
|
@@ -6,6 +6,9 @@ import {
|
|
|
6
6
|
} from '../xpath-evaluation.js';
|
|
7
7
|
import getInScopeContext from '../getInScopeContext.js';
|
|
8
8
|
import { Fore } from '../fore.js';
|
|
9
|
+
import {ModelItem} from "../modelitem.js";
|
|
10
|
+
import {debounce} from "../events.js";
|
|
11
|
+
import {FxModel} from "../fx-model";
|
|
9
12
|
|
|
10
13
|
const WIDGETCLASS = 'widget';
|
|
11
14
|
|
|
@@ -19,7 +22,8 @@ const WIDGETCLASS = 'widget';
|
|
|
19
22
|
* @demo demo/index.html
|
|
20
23
|
*/
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
/*
|
|
26
|
+
function debounce( func, timeout = 300) {
|
|
23
27
|
let timer;
|
|
24
28
|
return (...args) => {
|
|
25
29
|
clearTimeout(timer);
|
|
@@ -28,6 +32,7 @@ function debounce(func, timeout = 300) {
|
|
|
28
32
|
}, timeout);
|
|
29
33
|
};
|
|
30
34
|
}
|
|
35
|
+
*/
|
|
31
36
|
export default class FxControl extends XfAbstractControl {
|
|
32
37
|
constructor() {
|
|
33
38
|
super();
|
|
@@ -71,10 +76,16 @@ export default class FxControl extends XfAbstractControl {
|
|
|
71
76
|
listenOn = target;
|
|
72
77
|
}
|
|
73
78
|
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
this.addEventListener('keyup', event => {
|
|
82
|
+
FxModel.dataChanged = true;
|
|
83
|
+
});
|
|
74
84
|
// ### convenience marker event
|
|
75
85
|
if (this.updateEvent === 'enter') {
|
|
76
86
|
this.widget.addEventListener('keyup', event => {
|
|
77
87
|
if (event.keyCode === 13) {
|
|
88
|
+
// console.info('handling Event:', event.type, listenOn);
|
|
78
89
|
// Cancel the default action, if needed
|
|
79
90
|
event.preventDefault();
|
|
80
91
|
this.setValue(this.widget[this.valueProp]);
|
|
@@ -85,14 +96,15 @@ export default class FxControl extends XfAbstractControl {
|
|
|
85
96
|
if (this.debounceDelay) {
|
|
86
97
|
listenOn.addEventListener(
|
|
87
98
|
this.updateEvent,
|
|
88
|
-
debounce(() => {
|
|
89
|
-
console.log('eventlistener ', this.updateEvent);
|
|
99
|
+
debounce(this,() => {
|
|
100
|
+
// console.log('eventlistener ', this.updateEvent);
|
|
101
|
+
// console.info('handling Event:', event.type, listenOn);
|
|
90
102
|
this.setValue(this.widget[this.valueProp]);
|
|
91
103
|
}, this.debounceDelay),
|
|
92
104
|
);
|
|
93
105
|
} else {
|
|
94
106
|
listenOn.addEventListener(this.updateEvent, () => {
|
|
95
|
-
console.
|
|
107
|
+
// console.info('handling Event:', event.type, listenOn);
|
|
96
108
|
this.setValue(this.widget[this.valueProp]);
|
|
97
109
|
});
|
|
98
110
|
}
|
|
@@ -124,6 +136,8 @@ export default class FxControl extends XfAbstractControl {
|
|
|
124
136
|
});
|
|
125
137
|
|
|
126
138
|
this.template = this.querySelector('template');
|
|
139
|
+
this.boundInitialized = false;
|
|
140
|
+
this.static = this.widget.hasAttribute('static')? true:false;
|
|
127
141
|
// console.log('template',this.template);
|
|
128
142
|
}
|
|
129
143
|
|
|
@@ -149,6 +163,8 @@ export default class FxControl extends XfAbstractControl {
|
|
|
149
163
|
setValue(val) {
|
|
150
164
|
const modelitem = this.getModelItem();
|
|
151
165
|
|
|
166
|
+
this.classList.add('visited');
|
|
167
|
+
|
|
152
168
|
if (modelitem?.readonly){
|
|
153
169
|
console.warn('attempt to change readonly node', modelitem);
|
|
154
170
|
return; // do nothing when modelItem is readonly
|
|
@@ -160,13 +176,20 @@ export default class FxControl extends XfAbstractControl {
|
|
|
160
176
|
replace.replace(this.nodeset, this.getWidget().value);
|
|
161
177
|
if (modelitem && widgetValue && widgetValue !== modelitem.value) {
|
|
162
178
|
modelitem.value = widgetValue;
|
|
179
|
+
FxModel.dataChanged = true;
|
|
163
180
|
replace.actionPerformed();
|
|
164
181
|
}
|
|
165
182
|
return;
|
|
166
183
|
}
|
|
167
184
|
const setval = this.shadowRoot.getElementById('setvalue');
|
|
168
185
|
setval.setValue(modelitem, val);
|
|
186
|
+
|
|
187
|
+
if (this.modelItem instanceof ModelItem && !this.modelItem?.boundControls.includes(this)) {
|
|
188
|
+
this.modelItem.boundControls.push(this);
|
|
189
|
+
}
|
|
190
|
+
|
|
169
191
|
setval.actionPerformed();
|
|
192
|
+
this.visited = true;
|
|
170
193
|
}
|
|
171
194
|
|
|
172
195
|
_replaceNode(node) {
|
|
@@ -262,7 +285,7 @@ export default class FxControl extends XfAbstractControl {
|
|
|
262
285
|
widget.value = this.nodeset.cloneNode(true);
|
|
263
286
|
// todo: should be more like below but that can cause infinite loop when controll trigger update event due to calling a setter for property
|
|
264
287
|
// widget[this.valueProp] = this.nodeset.cloneNode(true);
|
|
265
|
-
console.log('passed value to widget', widget.value);
|
|
288
|
+
// console.log('passed value to widget', widget.value);
|
|
266
289
|
}
|
|
267
290
|
|
|
268
291
|
return;
|
|
@@ -271,6 +294,7 @@ export default class FxControl extends XfAbstractControl {
|
|
|
271
294
|
// ### when there's a url Fore is used as widget and will be loaded from external file
|
|
272
295
|
if (this.url && !this.loaded) {
|
|
273
296
|
// ### evaluate initial data if necessary
|
|
297
|
+
|
|
274
298
|
if (this.initial) {
|
|
275
299
|
this.initialNode = evaluateXPathToFirstNode(this.initial, this.nodeset, this);
|
|
276
300
|
console.log('initialNodes', this.initialNode);
|
|
@@ -309,7 +333,11 @@ export default class FxControl extends XfAbstractControl {
|
|
|
309
333
|
* @private
|
|
310
334
|
*/
|
|
311
335
|
async _loadForeFromUrl() {
|
|
312
|
-
console.log('########## loading Fore from ', this.
|
|
336
|
+
console.log('########## loading Fore from ', this.url, '##########');
|
|
337
|
+
console.info(
|
|
338
|
+
`%cFore is processing URL ${this.url}`,
|
|
339
|
+
"background:#64b5f6; color:white; padding:1rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;",
|
|
340
|
+
);
|
|
313
341
|
try {
|
|
314
342
|
const response = await fetch(this.url, {
|
|
315
343
|
method: 'GET',
|
|
@@ -319,6 +347,7 @@ export default class FxControl extends XfAbstractControl {
|
|
|
319
347
|
'Content-Type': 'text/html',
|
|
320
348
|
},
|
|
321
349
|
});
|
|
350
|
+
|
|
322
351
|
const responseContentType = response.headers.get('content-type').toLowerCase();
|
|
323
352
|
console.log('********** responseContentType *********', responseContentType);
|
|
324
353
|
let data;
|
|
@@ -332,37 +361,42 @@ export default class FxControl extends XfAbstractControl {
|
|
|
332
361
|
}
|
|
333
362
|
// const theFore = fxEvaluateXPathToFirstNode('//fx-fore', data.firstElementChild);
|
|
334
363
|
const theFore = data.querySelector('fx-fore');
|
|
364
|
+
const imported = document.importNode(theFore,true);
|
|
365
|
+
|
|
335
366
|
// console.log('thefore', theFore)
|
|
336
|
-
|
|
367
|
+
imported.classList.add('widget'); // is the new widget
|
|
368
|
+
console.log(`########## loaded fore as component ##### ${this.url}`);
|
|
369
|
+
imported.addEventListener(
|
|
370
|
+
'model-construct-done',
|
|
371
|
+
e => {
|
|
372
|
+
console.log('subcomponent ready', e.target);
|
|
373
|
+
const defaultInst = imported.querySelector('fx-instance');
|
|
374
|
+
// console.log('defaultInst', defaultInst);
|
|
375
|
+
if(this.initialNode){
|
|
376
|
+
const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
377
|
+
// Note: Clone the input to prevent the inner fore from editing the outer node
|
|
378
|
+
doc.firstElementChild.appendChild(this.initialNode.cloneNode(true));
|
|
379
|
+
// defaultinst.setInstanceData(this.initialNode);
|
|
380
|
+
defaultInst.setInstanceData(doc);
|
|
381
|
+
}
|
|
382
|
+
// console.log('new data', defaultInst.getInstanceData());
|
|
383
|
+
// theFore.getModel().modelConstruct();
|
|
384
|
+
imported.getModel().updateModel();
|
|
385
|
+
imported.refresh();
|
|
386
|
+
},
|
|
387
|
+
{ once: true },
|
|
388
|
+
);
|
|
389
|
+
|
|
337
390
|
const dummy = this.querySelector('input');
|
|
338
391
|
if (this.hasAttribute('shadow')) {
|
|
339
392
|
dummy.parentNode.removeChild(dummy);
|
|
340
|
-
this.shadowRoot.appendChild(
|
|
393
|
+
this.shadowRoot.appendChild(imported);
|
|
341
394
|
} else {
|
|
342
|
-
|
|
395
|
+
console.log(this, 'replacing widget with',theFore);
|
|
396
|
+
dummy.replaceWith(imported);
|
|
397
|
+
// this.appendChild(imported);
|
|
343
398
|
}
|
|
344
399
|
|
|
345
|
-
console.log(`########## loaded fore as component ##### ${this.url}`);
|
|
346
|
-
theFore.addEventListener(
|
|
347
|
-
'model-construct-done',
|
|
348
|
-
e => {
|
|
349
|
-
console.log('subcomponent ready', e.target);
|
|
350
|
-
const defaultInst = theFore.querySelector('fx-instance');
|
|
351
|
-
console.log('defaultInst', defaultInst);
|
|
352
|
-
if(this.initialNode){
|
|
353
|
-
const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
354
|
-
// Note: Clone the input to prevent the inner fore from editing the outer node
|
|
355
|
-
doc.firstElementChild.appendChild(this.initialNode.cloneNode(true));
|
|
356
|
-
// defaultinst.setInstanceData(this.initialNode);
|
|
357
|
-
defaultInst.setInstanceData(doc);
|
|
358
|
-
}
|
|
359
|
-
console.log('new data', defaultInst.getInstanceData());
|
|
360
|
-
// theFore.getModel().modelConstruct();
|
|
361
|
-
theFore.getModel().updateModel();
|
|
362
|
-
theFore.refresh();
|
|
363
|
-
},
|
|
364
|
-
{ once: true },
|
|
365
|
-
);
|
|
366
400
|
|
|
367
401
|
if (!theFore) {
|
|
368
402
|
this.dispatchEvent(
|
|
@@ -408,6 +442,8 @@ export default class FxControl extends XfAbstractControl {
|
|
|
408
442
|
* @private
|
|
409
443
|
*/
|
|
410
444
|
_handleBoundWidget(widget) {
|
|
445
|
+
if(this.boundInitialized && this.static) return;
|
|
446
|
+
|
|
411
447
|
if (widget && widget.hasAttribute('ref')) {
|
|
412
448
|
// ### eval nodeset for list control
|
|
413
449
|
const ref = widget.getAttribute('ref');
|
|
@@ -445,18 +481,36 @@ export default class FxControl extends XfAbstractControl {
|
|
|
445
481
|
|
|
446
482
|
if (nodeset.length) {
|
|
447
483
|
// console.log('nodeset', nodeset);
|
|
484
|
+
const fragment = document.createDocumentFragment();
|
|
485
|
+
console.time('offscreen');
|
|
486
|
+
/*
|
|
487
|
+
Array.from(nodeset).forEach(node => {
|
|
488
|
+
// console.log('#### node', node);
|
|
489
|
+
const newEntry = this.createEntry();
|
|
490
|
+
this.template.parentNode.appendChild(newEntry);
|
|
491
|
+
// ### initialize new entry
|
|
492
|
+
// ### set value
|
|
493
|
+
this.updateEntry(newEntry, node);
|
|
494
|
+
});
|
|
495
|
+
*/
|
|
496
|
+
// this should actually perform better than the above but does not seem to make a measurable difference.
|
|
448
497
|
Array.from(nodeset).forEach(node => {
|
|
449
498
|
// console.log('#### node', node);
|
|
450
499
|
const newEntry = this.createEntry();
|
|
500
|
+
fragment.appendChild(newEntry);
|
|
451
501
|
|
|
452
502
|
// ### initialize new entry
|
|
453
503
|
// ### set value
|
|
454
504
|
this.updateEntry(newEntry, node);
|
|
455
505
|
});
|
|
506
|
+
this.template.parentNode.appendChild(fragment);
|
|
507
|
+
console.timeEnd('offscreen');
|
|
456
508
|
} else {
|
|
457
509
|
const newEntry = this.createEntry();
|
|
510
|
+
this.template.parentNode.appendChild(newEntry);
|
|
458
511
|
this.updateEntry(newEntry, nodeset);
|
|
459
512
|
}
|
|
513
|
+
this.boundInitialized = true;
|
|
460
514
|
}
|
|
461
515
|
}
|
|
462
516
|
}
|
|
@@ -485,10 +539,12 @@ export default class FxControl extends XfAbstractControl {
|
|
|
485
539
|
}
|
|
486
540
|
|
|
487
541
|
createEntry() {
|
|
488
|
-
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
542
|
+
return this.template.content.firstElementChild.cloneNode(true);
|
|
543
|
+
// const content = this.template.content.firstElementChild.cloneNode(true);
|
|
544
|
+
// return content;
|
|
545
|
+
// const newEntry = document.importNode(content, true);
|
|
546
|
+
// this.template.parentNode.appendChild(newEntry);
|
|
547
|
+
// return newEntry;
|
|
492
548
|
}
|
|
493
549
|
|
|
494
550
|
// eslint-disable-next-line class-methods-use-this
|
package/src/ui/fx-group.js
CHANGED
package/src/ui/fx-inspector.js
CHANGED
|
@@ -25,6 +25,7 @@ export class FxInspector extends HTMLElement {
|
|
|
25
25
|
/*max-height: 33%;*/
|
|
26
26
|
overflow: scroll;
|
|
27
27
|
transition:width 0.3s ease;
|
|
28
|
+
z-index:100;
|
|
28
29
|
}
|
|
29
30
|
:host([open]){
|
|
30
31
|
width: 30%;
|
|
@@ -121,7 +122,6 @@ export class FxInspector extends HTMLElement {
|
|
|
121
122
|
</div>
|
|
122
123
|
`;
|
|
123
124
|
|
|
124
|
-
/*
|
|
125
125
|
const handle = this.shadowRoot.querySelector('.handle');
|
|
126
126
|
handle.addEventListener('click', e => {
|
|
127
127
|
// console.log('toggling');
|
|
@@ -132,10 +132,13 @@ export class FxInspector extends HTMLElement {
|
|
|
132
132
|
this.setAttribute('open', 'open');
|
|
133
133
|
}
|
|
134
134
|
});
|
|
135
|
-
*/
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
serializeDOM(data) {
|
|
138
|
+
if(!data){
|
|
139
|
+
console.warn('no data to serialize');
|
|
140
|
+
return ;
|
|
141
|
+
}
|
|
139
142
|
// console.log('serializeDOM', data);
|
|
140
143
|
const ser = new XMLSerializer().serializeToString(data);
|
|
141
144
|
return Fore.prettifyXml(ser);
|
package/src/ui/fx-output.js
CHANGED
|
@@ -51,8 +51,9 @@ export class FxOutput extends XfAbstractControl {
|
|
|
51
51
|
|
|
52
52
|
const outputHtml = `
|
|
53
53
|
<slot name="label"></slot>
|
|
54
|
+
|
|
54
55
|
<span id="value">
|
|
55
|
-
<slot
|
|
56
|
+
<slot></slot>
|
|
56
57
|
</span>
|
|
57
58
|
`;
|
|
58
59
|
|
|
@@ -67,9 +68,11 @@ export class FxOutput extends XfAbstractControl {
|
|
|
67
68
|
// console.log('widget ', this.widget);
|
|
68
69
|
this.mediatype = this.hasAttribute('mediatype') ? this.getAttribute('mediatype') : null;
|
|
69
70
|
|
|
71
|
+
/*
|
|
70
72
|
this.addEventListener('slotchange', e => {
|
|
71
73
|
console.log('slotchange ', e);
|
|
72
74
|
});
|
|
75
|
+
*/
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
async refresh() {
|
|
@@ -112,13 +115,14 @@ export class FxOutput extends XfAbstractControl {
|
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
async updateWidgetValue() {
|
|
115
|
-
console.log('updateWidgetValue');
|
|
118
|
+
// console.log('updateWidgetValue');
|
|
116
119
|
const valueWrapper = this.shadowRoot.getElementById('value');
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
|
|
122
|
+
// if (this.mediatype === 'markdown') {
|
|
123
|
+
// const md = markdown(this.nodeset);
|
|
124
|
+
// this.innerHtml = md;
|
|
125
|
+
// }
|
|
122
126
|
|
|
123
127
|
if (this.mediatype === 'html') {
|
|
124
128
|
if (this.modelItem.node) {
|
|
@@ -130,16 +134,7 @@ export class FxOutput extends XfAbstractControl {
|
|
|
130
134
|
const { node } = this.modelItem;
|
|
131
135
|
|
|
132
136
|
if (node.nodeType) {
|
|
133
|
-
// const mainSlot = this.shadowRoot.querySelector('#main');
|
|
134
|
-
// valueWrapper.appendChild(node);
|
|
135
|
-
|
|
136
|
-
// todo: checking if ownerDocument of node and ownerDocument of this are the same - otherwise import first
|
|
137
|
-
// const imported = this.ownerDocument.importNode(node,true);
|
|
138
|
-
// const clone = node.cloneNode(true);
|
|
139
|
-
|
|
140
137
|
this.appendChild(node);
|
|
141
|
-
// this.innerHtml = node;
|
|
142
|
-
// this.innerHTML = node;
|
|
143
138
|
return;
|
|
144
139
|
}
|
|
145
140
|
Object.entries(node).map(obj => {
|
|
@@ -156,6 +151,13 @@ export class FxOutput extends XfAbstractControl {
|
|
|
156
151
|
return;
|
|
157
152
|
}
|
|
158
153
|
|
|
154
|
+
if(this.mediatype === 'image'){
|
|
155
|
+
const img = document.createElement('img');
|
|
156
|
+
img.setAttribute('src',this.value);
|
|
157
|
+
this.appendChild(img);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
159
161
|
valueWrapper.innerHTML = this.value;
|
|
160
162
|
}
|
|
161
163
|
|
package/src/ui/fx-repeat.js
CHANGED
|
@@ -212,7 +212,7 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
|
212
212
|
// console.group('fx-repeat.refresh on', this.id);
|
|
213
213
|
|
|
214
214
|
if (!this.inited) this.init();
|
|
215
|
-
console.time('repeat-refresh', this);
|
|
215
|
+
// console.time('repeat-refresh', this);
|
|
216
216
|
this._evalNodeset();
|
|
217
217
|
// console.log('repeat refresh nodeset ', this.nodeset);
|
|
218
218
|
// console.log('repeatCount', this.repeatCount);
|
|
@@ -275,7 +275,7 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
|
|
|
275
275
|
// this.style.display = 'block';
|
|
276
276
|
// this.style.display = this.display;
|
|
277
277
|
this.setIndex(this.index);
|
|
278
|
-
console.timeEnd('repeat-refresh');
|
|
278
|
+
// console.timeEnd('repeat-refresh');
|
|
279
279
|
|
|
280
280
|
// this.replaceWith(clone);
|
|
281
281
|
|
package/src/ui/fx-repeatitem.js
CHANGED
|
@@ -43,7 +43,7 @@ export class FxRepeatitem extends foreElementMixin(HTMLElement) {
|
|
|
43
43
|
// console.log('_dispatchIndexChange on index ', this.index);
|
|
44
44
|
if (this.parentNode) {
|
|
45
45
|
this.parentNode.dispatchEvent(
|
|
46
|
-
new CustomEvent('item-changed', { composed:
|
|
46
|
+
new CustomEvent('item-changed', { composed: false, bubbles: true, detail: { item: this , index:this.index } }),
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -90,12 +90,14 @@ export class FxRepeatitem extends foreElementMixin(HTMLElement) {
|
|
|
90
90
|
|
|
91
91
|
if (this.modelItem && !this.modelItem.relevant) {
|
|
92
92
|
// await Fore.fadeOutElement(this)
|
|
93
|
-
this.style.display = 'none';
|
|
93
|
+
// this.style.display = 'none';
|
|
94
|
+
this.classList.add('nonrelevant');
|
|
94
95
|
} else {
|
|
95
96
|
// if(this.hasAttribute('repeat-index')){
|
|
96
97
|
// Fore.fadeInElement(this);
|
|
97
98
|
// }
|
|
98
|
-
this.style.display = this.display;
|
|
99
|
+
// this.style.display = this.display;
|
|
100
|
+
this.classList.remove('nonrelevant');
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
/*
|
package/src/ui/fx-switch.js
CHANGED
|
@@ -36,28 +36,31 @@ class FxSwitch extends FxContainer {
|
|
|
36
36
|
`;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
refresh() {
|
|
39
|
+
async refresh(force) {
|
|
40
40
|
super.refresh();
|
|
41
|
-
console.log('refresh on switch ');
|
|
41
|
+
// console.log('refresh on switch ');
|
|
42
42
|
const cases = this.querySelectorAll(':scope > fx-case');
|
|
43
|
+
let selectedCase;
|
|
43
44
|
if (this.isBound()) {
|
|
44
45
|
Array.from(cases).forEach(caseElem => {
|
|
45
46
|
const name = caseElem.getAttribute('name');
|
|
46
47
|
if (name === this.modelItem.value) {
|
|
47
48
|
caseElem.classList.add('selected-case');
|
|
49
|
+
selectedCase = caseElem;
|
|
48
50
|
} else {
|
|
49
51
|
caseElem.classList.remove('selected-case');
|
|
50
52
|
}
|
|
51
53
|
});
|
|
52
54
|
} else {
|
|
53
|
-
|
|
54
|
-
if
|
|
55
|
-
|
|
55
|
+
selectedCase = this.querySelector(':scope > .selected-case');
|
|
56
|
+
// if none is selected select the first as default
|
|
57
|
+
if (!selectedCase) {
|
|
58
|
+
selectedCase = cases[0];
|
|
59
|
+
selectedCase.classList.add('selected-case');
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
Fore.refreshChildren(
|
|
60
|
-
// console.log('value ', this.value);
|
|
63
|
+
Fore.refreshChildren(selectedCase,force);
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
toggle(caseElement) {
|
|
@@ -66,6 +69,7 @@ class FxSwitch extends FxContainer {
|
|
|
66
69
|
if (caseElement === c) {
|
|
67
70
|
// eslint-disable-next-line no-param-reassign
|
|
68
71
|
c.classList.add('selected-case');
|
|
72
|
+
this.refresh();
|
|
69
73
|
} else {
|
|
70
74
|
// eslint-disable-next-line no-param-reassign
|
|
71
75
|
c.classList.remove('selected-case');
|
package/src/ui/fx-trigger.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import XfAbstractControl from './abstract-control.js';
|
|
2
|
+
import {leadingDebounce} from "../events.js";
|
|
2
3
|
|
|
3
4
|
export class FxTrigger extends XfAbstractControl {
|
|
4
5
|
connectedCallback() {
|
|
5
6
|
this.attachShadow({ mode: 'open' });
|
|
6
7
|
this.ref = this.hasAttribute('ref') ? this.getAttribute('ref') : null;
|
|
8
|
+
this.debounceDelay = this.hasAttribute('debounce') ? this.getAttribute('debounce') : null;
|
|
9
|
+
|
|
7
10
|
const style = `
|
|
8
11
|
:host {
|
|
9
12
|
cursor:pointer;
|
|
@@ -24,7 +27,17 @@ export class FxTrigger extends XfAbstractControl {
|
|
|
24
27
|
elements[0].setAttribute('role', 'button');
|
|
25
28
|
|
|
26
29
|
const element = elements[0];
|
|
27
|
-
|
|
30
|
+
|
|
31
|
+
if(this.debounceDelay){
|
|
32
|
+
this.addEventListener(
|
|
33
|
+
'click',
|
|
34
|
+
leadingDebounce(this,(e) => {
|
|
35
|
+
this.performActions(e)
|
|
36
|
+
}, this.debounceDelay),
|
|
37
|
+
);
|
|
38
|
+
}else{
|
|
39
|
+
element.addEventListener('click', e => this.performActions(e));
|
|
40
|
+
}
|
|
28
41
|
this.widget = element;
|
|
29
42
|
// # terrible hack but browser behaves strange - seems to fire a 'click' for a button when it receives a
|
|
30
43
|
// # 'Space' or 'Enter' key
|
|
@@ -36,14 +49,6 @@ export class FxTrigger extends XfAbstractControl {
|
|
|
36
49
|
});
|
|
37
50
|
}
|
|
38
51
|
});
|
|
39
|
-
/*
|
|
40
|
-
this.addEventListener('click', e => this.performActions(e));
|
|
41
|
-
this.addEventListener('keypress', (e) => {
|
|
42
|
-
if(e.code === 'Space' || e.code === 'Enter'){
|
|
43
|
-
this.performActions(e);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
*/
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
// eslint-disable-next-line class-methods-use-this
|
|
@@ -89,6 +94,7 @@ export class FxTrigger extends XfAbstractControl {
|
|
|
89
94
|
if (typeof child.execute === 'function') {
|
|
90
95
|
// eslint-disable-next-line no-await-in-loop
|
|
91
96
|
await child.execute(e);
|
|
97
|
+
// child.execute(e);
|
|
92
98
|
}
|
|
93
99
|
}
|
|
94
100
|
};
|
package/src/xpath-evaluation.js
CHANGED
|
@@ -146,6 +146,30 @@ export function resolveId(id, sourceObject, nodeName = null) {
|
|
|
146
146
|
// Make namespace resolving use the `instance` element that is related to here
|
|
147
147
|
const xmlDocument = new DOMParser().parseFromString('<xml />', 'text/xml');
|
|
148
148
|
|
|
149
|
+
function findInstanceReferences(xpathQuery) {
|
|
150
|
+
if (!xpathQuery.includes('instance')) {
|
|
151
|
+
// No call to the instance function anyway: short-circuit and prevent AST processing
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
const xpathAST = parseScript(xpathQuery, {}, xmlDocument);
|
|
155
|
+
const instanceReferences = fxEvaluateXPathToStrings(
|
|
156
|
+
`descendant::xqx:functionCallExpr
|
|
157
|
+
[xqx:functionName = "instance"]
|
|
158
|
+
/xqx:arguments
|
|
159
|
+
/xqx:stringConstantExpr
|
|
160
|
+
/xqx:value`,
|
|
161
|
+
xpathAST,
|
|
162
|
+
null,
|
|
163
|
+
{},
|
|
164
|
+
{
|
|
165
|
+
namespaceResolver: prefix =>
|
|
166
|
+
prefix === 'xqx' ? 'http://www.w3.org/2005/XQueryX' : undefined,
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return instanceReferences;
|
|
171
|
+
}
|
|
172
|
+
|
|
149
173
|
/**
|
|
150
174
|
* Resolve a namespace. Needs a namespace prefix and the element that is most closely related to the
|
|
151
175
|
* XPath in which the namespace is being resolved. The prefix will be resolved by using the
|
|
@@ -165,25 +189,12 @@ function createNamespaceResolver(xpathQuery, formElement) {
|
|
|
165
189
|
if (cachedResolver) {
|
|
166
190
|
return cachedResolver;
|
|
167
191
|
}
|
|
168
|
-
|
|
169
|
-
const xpathAST = parseScript(xpathQuery, {}, xmlDocument);
|
|
170
|
-
let instanceReferences = fxEvaluateXPathToStrings(
|
|
171
|
-
`descendant::xqx:functionCallExpr
|
|
172
|
-
[xqx:functionName = "instance"]
|
|
173
|
-
/xqx:arguments
|
|
174
|
-
/xqx:stringConstantExpr
|
|
175
|
-
/xqx:value`,
|
|
176
|
-
xpathAST,
|
|
177
|
-
null,
|
|
178
|
-
{},
|
|
179
|
-
{
|
|
180
|
-
namespaceResolver: prefix =>
|
|
181
|
-
prefix === 'xqx' ? 'http://www.w3.org/2005/XQueryX' : undefined,
|
|
182
|
-
},
|
|
183
|
-
);
|
|
192
|
+
let instanceReferences = findInstanceReferences(xpathQuery);
|
|
184
193
|
if (instanceReferences.length === 0) {
|
|
185
194
|
// No instance functions. Look up further in the hierarchy to see if we can deduce the intended context from there
|
|
186
|
-
const ancestorComponent =
|
|
195
|
+
const ancestorComponent = formElement.parentNode &&
|
|
196
|
+
formElement.parentNode.nodeType === formElement.ELEMENT &&
|
|
197
|
+
formElement.parentNode.closest('[ref]');
|
|
187
198
|
if (ancestorComponent) {
|
|
188
199
|
const resolver = createNamespaceResolver(
|
|
189
200
|
ancestorComponent.getAttribute('ref'),
|
|
@@ -327,7 +338,9 @@ function getVariablesInScope(formElement) {
|
|
|
327
338
|
if (closestActualFormElement.inScopeVariables) {
|
|
328
339
|
for (const key of closestActualFormElement.inScopeVariables.keys()) {
|
|
329
340
|
const varElement = closestActualFormElement.inScopeVariables.get(key);
|
|
330
|
-
|
|
341
|
+
if(varElement){
|
|
342
|
+
variables[key] = varElement.value;
|
|
343
|
+
}
|
|
331
344
|
}
|
|
332
345
|
}
|
|
333
346
|
return variables;
|