@jinntec/fore 2.4.2 → 2.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 +34262 -3
- package/dist/fore.js +34124 -3
- package/index.js +2 -0
- package/package.json +2 -2
- package/resources/fore.css +30 -1
- package/src/DataObserver.js +181 -0
- package/src/DependentXPathQueries.js +32 -0
- package/src/ForeElementMixin.js +289 -254
- package/src/actions/abstract-action.js +38 -5
- package/src/actions/fx-append.js +2 -0
- package/src/actions/fx-delete.js +13 -1
- package/src/actions/fx-hide.js +1 -1
- package/src/actions/fx-insert.js +47 -39
- package/src/actions/fx-load.js +7 -2
- package/src/actions/fx-send.js +0 -2
- package/src/actions/fx-setvalue.js +104 -82
- package/src/actions/fx-show.js +4 -2
- package/src/fore.js +40 -22
- package/src/fx-bind.js +3 -2
- package/src/fx-fore.js +320 -164
- package/src/fx-instance.js +3 -2
- package/src/fx-model.js +63 -34
- package/src/fx-submission.js +38 -22
- package/src/getInScopeContext.js +2 -1
- package/src/modelitem.js +107 -91
- package/src/ui/UIElement.js +91 -0
- package/src/ui/abstract-control.js +14 -9
- package/src/ui/fx-container.js +7 -4
- package/src/ui/fx-control-menu.js +198 -0
- package/src/ui/fx-control.js +64 -41
- package/src/ui/fx-dialog.js +2 -2
- package/src/ui/fx-group.js +14 -0
- package/src/ui/fx-repeat.js +42 -3
- package/src/ui/fx-repeatitem.js +3 -0
- package/src/ui/fx-upload.js +304 -0
- package/src/xpath-util.js +310 -168
- package/dist/fore-dev.js.map +0 -1
- package/dist/fore.js.map +0 -1
|
@@ -122,6 +122,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
122
122
|
disconnectedCallback() {}
|
|
123
123
|
|
|
124
124
|
connectedCallback() {
|
|
125
|
+
super.connectedCallback();
|
|
125
126
|
this.setAttribute('inert', 'true');
|
|
126
127
|
this.style.display = 'none';
|
|
127
128
|
this.propagate = this.hasAttribute('propagate') ? this.getAttribute('propagate') : 'continue';
|
|
@@ -176,6 +177,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
176
177
|
}
|
|
177
178
|
} else {
|
|
178
179
|
this.targetElement = this.parentNode;
|
|
180
|
+
if(!this.targetElement || this.targetElement.nodeType !== Node.ELEMENT_NODE) return;
|
|
179
181
|
this.targetElement.addEventListener(this.event, e => this.execute(e), {
|
|
180
182
|
capture: this.phase === 'capture',
|
|
181
183
|
});
|
|
@@ -212,8 +214,27 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
212
214
|
* @param e
|
|
213
215
|
*/
|
|
214
216
|
async execute(e) {
|
|
215
|
-
if(!this.getModel().modelConstructed) return;
|
|
217
|
+
if (!this.getModel().modelConstructed) return;
|
|
216
218
|
// console.log(this, this.event);
|
|
219
|
+
if (this.event) {
|
|
220
|
+
if (this.event === 'submit-done') {
|
|
221
|
+
console.info(
|
|
222
|
+
`%csubmit-done ${this.event} #${this?.parentNode?.id}`,
|
|
223
|
+
'background:lime; color:black; padding:.5rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;',
|
|
224
|
+
);
|
|
225
|
+
} else {
|
|
226
|
+
console.info(
|
|
227
|
+
`%cexecuting ${this.constructor.name} ${this.event}`,
|
|
228
|
+
'background:lime; color:black; padding:.5rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;',
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
console.info(
|
|
233
|
+
`%cexecuting ${this.constructor.name}`,
|
|
234
|
+
'background:limegreen; color:black; margin-left:1rem; padding:.5rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;width:100%;',
|
|
235
|
+
this,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
217
238
|
|
|
218
239
|
if (e && e.target.nodeType !== Node.DOCUMENT_NODE && e.target !== window) {
|
|
219
240
|
/*
|
|
@@ -239,7 +260,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
239
260
|
let resolveThisEvent = () => {};
|
|
240
261
|
if (e && e.listenerPromises) {
|
|
241
262
|
e.listenerPromises.push(
|
|
242
|
-
new Promise(
|
|
263
|
+
new Promise(resolve => {
|
|
243
264
|
resolveThisEvent = resolve;
|
|
244
265
|
}),
|
|
245
266
|
);
|
|
@@ -247,6 +268,12 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
247
268
|
|
|
248
269
|
// Outermost handling
|
|
249
270
|
if (FxFore.outermostHandler === null) {
|
|
271
|
+
console.log(
|
|
272
|
+
`%coutermost Action on ${this.getOwnerForm().id}`,
|
|
273
|
+
'background:darkblue; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;',
|
|
274
|
+
this,
|
|
275
|
+
);
|
|
276
|
+
|
|
250
277
|
FxFore.outermostHandler = this;
|
|
251
278
|
this.dispatchEvent(
|
|
252
279
|
new CustomEvent('outermost-action-start', {
|
|
@@ -378,6 +405,12 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
378
405
|
this.currentEvent = null;
|
|
379
406
|
this.actionPerformed();
|
|
380
407
|
if (FxFore.outermostHandler === this) {
|
|
408
|
+
console.log(
|
|
409
|
+
`%cfinalizing outermost Action on ${this.getOwnerForm().id}`,
|
|
410
|
+
'background:darkblue; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;',
|
|
411
|
+
this,
|
|
412
|
+
);
|
|
413
|
+
|
|
381
414
|
FxFore.outermostHandler = null;
|
|
382
415
|
/*
|
|
383
416
|
console.info(
|
|
@@ -434,8 +467,8 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
434
467
|
return;
|
|
435
468
|
}
|
|
436
469
|
if (
|
|
437
|
-
FxFore.outermostHandler
|
|
438
|
-
|
|
470
|
+
FxFore.outermostHandler &&
|
|
471
|
+
!XPathUtil.contains(FxFore.outermostHandler.ownerDocument, FxFore.outermostHandler)
|
|
439
472
|
) {
|
|
440
473
|
// The old outermostHandler fell out of the document. An error has happened.
|
|
441
474
|
// Just remove the old one and act like we are starting anew.
|
|
@@ -447,7 +480,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
447
480
|
// console.log('running update cycle for outermostHandler', this);
|
|
448
481
|
model.recalculate();
|
|
449
482
|
model.revalidate();
|
|
450
|
-
|
|
483
|
+
this.getOwnerForm().refresh(true);
|
|
451
484
|
this.dispatchActionPerformed();
|
|
452
485
|
} else if (this.needsUpdate) {
|
|
453
486
|
// console.log('Update delayed!');
|
package/src/actions/fx-append.js
CHANGED
|
@@ -109,6 +109,8 @@ class FxAppend extends AbstractAction {
|
|
|
109
109
|
const data = this._generateInstance(templ.content, rootNode);
|
|
110
110
|
// console.log('_dataFromTemplate DATA', data);
|
|
111
111
|
inscope.appendChild(data);
|
|
112
|
+
parentForm.signalChangeToElement(inscope.localName);
|
|
113
|
+
parentForm.signalChangeToElement(data.localName);
|
|
112
114
|
// console.log('appended new item ', data);
|
|
113
115
|
// return data;
|
|
114
116
|
}
|
package/src/actions/fx-delete.js
CHANGED
|
@@ -52,19 +52,31 @@ class FxDelete extends AbstractAction {
|
|
|
52
52
|
}),
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
+
const fore = this.getOwnerForm();
|
|
56
|
+
|
|
55
57
|
let parent;
|
|
56
58
|
if (Array.isArray(nodesToDelete)) {
|
|
57
59
|
if (nodesToDelete.length === 0) return;
|
|
58
60
|
parent = nodesToDelete[0].parentNode;
|
|
61
|
+
fore.signalChangeToElement(parent.localName);
|
|
59
62
|
nodesToDelete.forEach(item => {
|
|
60
63
|
this._deleteNode(parent, item);
|
|
64
|
+
fore.signalChangeToElement(item.localName);
|
|
61
65
|
});
|
|
62
66
|
} else {
|
|
63
67
|
parent = nodesToDelete.parentNode;
|
|
68
|
+
fore.signalChangeToElement(parent.localName);
|
|
69
|
+
|
|
64
70
|
this._deleteNode(parent, nodesToDelete);
|
|
71
|
+
fore.signalChangeToElement(nodesToDelete.localName);
|
|
65
72
|
}
|
|
66
73
|
|
|
67
|
-
await Fore.dispatch(instance, 'deleted', {
|
|
74
|
+
await Fore.dispatch(instance, 'deleted', {
|
|
75
|
+
ref: path,
|
|
76
|
+
deletedNodes: nodesToDelete,
|
|
77
|
+
instanceId,
|
|
78
|
+
foreId: fore.id,
|
|
79
|
+
});
|
|
68
80
|
this.needsUpdate = true;
|
|
69
81
|
}
|
|
70
82
|
|
package/src/actions/fx-hide.js
CHANGED
package/src/actions/fx-insert.js
CHANGED
|
@@ -60,30 +60,6 @@ export class FxInsert extends AbstractAction {
|
|
|
60
60
|
this.keepValues = !!this.hasAttribute('keep-values');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
_getOriginSequence(inscope, targetSequence) {
|
|
64
|
-
let originSequence;
|
|
65
|
-
if (this.origin) {
|
|
66
|
-
// ### if there's an origin attribute use it
|
|
67
|
-
let originTarget;
|
|
68
|
-
try {
|
|
69
|
-
originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
|
|
70
|
-
if (Array.isArray(originTarget) && originTarget.length === 0) {
|
|
71
|
-
console.warn('invalid origin for this insert action - ignoring...', this);
|
|
72
|
-
originSequence = null;
|
|
73
|
-
}
|
|
74
|
-
originSequence = originTarget;
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.warn('invalid origin for this insert action - ignoring...', this);
|
|
77
|
-
}
|
|
78
|
-
} else if (targetSequence) {
|
|
79
|
-
// ### use last item of targetSequence
|
|
80
|
-
originSequence = targetSequence;
|
|
81
|
-
if (originSequence && !this.keepValues) {
|
|
82
|
-
this._clear(originSequence);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return originSequence;
|
|
86
|
-
}
|
|
87
63
|
|
|
88
64
|
_cloneOriginSequence(inscope, targetSequence) {
|
|
89
65
|
let originSequenceClone;
|
|
@@ -96,13 +72,25 @@ export class FxInsert extends AbstractAction {
|
|
|
96
72
|
*/
|
|
97
73
|
// this.setInScopeVariables(this.detail);
|
|
98
74
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
75
|
+
/*
|
|
76
|
+
if in 'create-nodes' mode and origin targets a repeat, the repeat
|
|
77
|
+
we use the already during initData() created nodeset as a template for insertion
|
|
78
|
+
*/
|
|
79
|
+
if(this.origin.startsWith('#') && this.getOwnerForm().createNodes){
|
|
80
|
+
const repeat = this.getOwnerForm().querySelector(this.origin);
|
|
81
|
+
originSequenceClone = repeat.createdNodeset.cloneNode(true);
|
|
82
|
+
if(!originSequenceClone){
|
|
83
|
+
console.error(`createdNodeset for repeat ${this.origin} does not exist`);
|
|
84
|
+
}
|
|
85
|
+
}else{
|
|
86
|
+
// originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
|
|
87
|
+
originTarget = evaluateXPathToFirstNode(this.origin, inscope, this);
|
|
88
|
+
if (Array.isArray(originTarget) && originTarget.length === 0) {
|
|
89
|
+
console.warn('invalid origin for this insert action - ignoring...', this);
|
|
90
|
+
originSequenceClone = null;
|
|
91
|
+
}
|
|
92
|
+
originSequenceClone = originTarget.cloneNode(true);
|
|
104
93
|
}
|
|
105
|
-
originSequenceClone = originTarget.cloneNode(true);
|
|
106
94
|
} catch (error) {
|
|
107
95
|
console.warn('invalid origin for this insert action - ignoring...', this);
|
|
108
96
|
}
|
|
@@ -136,13 +124,11 @@ export class FxInsert extends AbstractAction {
|
|
|
136
124
|
let targetSequence = [];
|
|
137
125
|
const inscopeContext = getInScopeContext(this);
|
|
138
126
|
|
|
127
|
+
const fore = this.getOwnerForm();
|
|
128
|
+
|
|
139
129
|
// ### 'context' attribute takes precedence over 'ref'
|
|
140
130
|
if (this.hasAttribute('context')) {
|
|
141
|
-
[context] = evaluateXPathToNodes(
|
|
142
|
-
this.getAttribute('context'),
|
|
143
|
-
inscopeContext,
|
|
144
|
-
this.getOwnerForm(),
|
|
145
|
-
);
|
|
131
|
+
[context] = evaluateXPathToNodes(this.getAttribute('context'), inscopeContext, fore);
|
|
146
132
|
inscope = inscopeContext;
|
|
147
133
|
}
|
|
148
134
|
|
|
@@ -154,6 +140,8 @@ export class FxInsert extends AbstractAction {
|
|
|
154
140
|
targetSequence = evaluateXPathToNodes(this.ref, inscope, this);
|
|
155
141
|
}
|
|
156
142
|
}
|
|
143
|
+
// const originSequenceClone = this._cloneOriginSequence(inscope, targetSequence);
|
|
144
|
+
|
|
157
145
|
const originSequenceClone = this._cloneOriginSequence(inscope, targetSequence);
|
|
158
146
|
if (!originSequenceClone) return; // if no origin back out without effect
|
|
159
147
|
|
|
@@ -165,12 +153,24 @@ export class FxInsert extends AbstractAction {
|
|
|
165
153
|
if (context) {
|
|
166
154
|
insertLocationNode = context;
|
|
167
155
|
context.appendChild(originSequenceClone);
|
|
156
|
+
fore.signalChangeToElement(insertLocationNode.localName);
|
|
157
|
+
fore.signalChangeToElement(originSequenceClone.localName);
|
|
168
158
|
index = 1;
|
|
169
159
|
} else {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
inscope.
|
|
173
|
-
|
|
160
|
+
|
|
161
|
+
// No context but creating nodes from UI
|
|
162
|
+
if(!inscope && this.getOwnerForm().createNodes){
|
|
163
|
+
const repeat = this.getOwnerForm().querySelector(this.origin);
|
|
164
|
+
inscope = getInScopeContext(repeat, repeat.ref);
|
|
165
|
+
insertLocationNode = inscope;
|
|
166
|
+
inscope.appendChild(originSequenceClone);
|
|
167
|
+
index = inscope.length - 1;
|
|
168
|
+
}else{
|
|
169
|
+
insertLocationNode = inscope;
|
|
170
|
+
inscope.appendChild(originSequenceClone);
|
|
171
|
+
index = 1;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
174
|
}
|
|
175
175
|
} else {
|
|
176
176
|
/* ### insert at position given by 'at' or use the last item in the targetSequence ### */
|
|
@@ -205,6 +205,8 @@ export class FxInsert extends AbstractAction {
|
|
|
205
205
|
if (this.position && this.position === 'before') {
|
|
206
206
|
// this.at -= 1;
|
|
207
207
|
insertLocationNode.parentNode.insertBefore(originSequenceClone, insertLocationNode);
|
|
208
|
+
fore.signalChangeToElement(insertLocationNode.parentNode);
|
|
209
|
+
fore.signalChangeToElement(originSequenceClone.localName);
|
|
208
210
|
}
|
|
209
211
|
|
|
210
212
|
if (this.position && this.position === 'after') {
|
|
@@ -217,8 +219,12 @@ export class FxInsert extends AbstractAction {
|
|
|
217
219
|
} else if (this.hasAttribute('context')) {
|
|
218
220
|
index = 1;
|
|
219
221
|
insertLocationNode.prepend(originSequenceClone);
|
|
222
|
+
fore.signalChangeToElement(insertLocationNode);
|
|
223
|
+
fore.signalChangeToElement(originSequenceClone.localName);
|
|
220
224
|
} else {
|
|
221
225
|
insertLocationNode.insertAdjacentElement('afterend', originSequenceClone);
|
|
226
|
+
fore.signalChangeToElement(insertLocationNode);
|
|
227
|
+
fore.signalChangeToElement(originSequenceClone.localName);
|
|
222
228
|
}
|
|
223
229
|
}
|
|
224
230
|
}
|
|
@@ -251,6 +257,8 @@ export class FxInsert extends AbstractAction {
|
|
|
251
257
|
'inserted-nodes': originSequenceClone,
|
|
252
258
|
'insert-location-node': insertLocationNode,
|
|
253
259
|
position: this.position,
|
|
260
|
+
instanceId,
|
|
261
|
+
foreId: fore.id,
|
|
254
262
|
});
|
|
255
263
|
|
|
256
264
|
// todo: this actually should dispatch to respective instance
|
package/src/actions/fx-load.js
CHANGED
|
@@ -27,12 +27,13 @@ class FxLoad extends AbstractAction {
|
|
|
27
27
|
super();
|
|
28
28
|
this.attachShadow({ mode: 'open' });
|
|
29
29
|
this.url = '';
|
|
30
|
+
this.replace=false;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
connectedCallback() {
|
|
33
34
|
super.connectedCallback();
|
|
34
35
|
this.attachTo = this.hasAttribute('attach-to') ? this.getAttribute('attach-to') : '_self';
|
|
35
|
-
|
|
36
|
+
this.replace = this.hasAttribute('replace') ? true : false;
|
|
36
37
|
// Add a 'doneEvent' to block the action chain untill the event fired on the element we're
|
|
37
38
|
// loading something into.
|
|
38
39
|
this.awaitEvent = this.hasAttribute('await') ? this.getAttribute('await') : '';
|
|
@@ -88,7 +89,11 @@ class FxLoad extends AbstractAction {
|
|
|
88
89
|
resolved.removeEventListener(this.awaitEvent, eventListener);
|
|
89
90
|
};
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
if(this.replace){
|
|
93
|
+
this.parentNode.replaceChild(content,resolved);
|
|
94
|
+
}else{
|
|
95
|
+
resolved.appendChild(content);
|
|
96
|
+
}
|
|
92
97
|
resolved.addEventListener(this.awaitEvent, eventListener);
|
|
93
98
|
|
|
94
99
|
await waitForEvent;
|
package/src/actions/fx-send.js
CHANGED
|
@@ -87,12 +87,10 @@ class FxSend extends AbstractAction {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
await submission.submit();
|
|
90
|
-
/*
|
|
91
90
|
if(submission.replace === 'instance'){
|
|
92
91
|
this.getModel().updateModel();
|
|
93
92
|
this.getOwnerForm().refresh();
|
|
94
93
|
}
|
|
95
|
-
*/
|
|
96
94
|
// if not of type fx-submission signal error
|
|
97
95
|
}
|
|
98
96
|
|
|
@@ -3,6 +3,7 @@ import '../fx-model.js';
|
|
|
3
3
|
import { AbstractAction } from './abstract-action.js';
|
|
4
4
|
import { evaluateXPath } from '../xpath-evaluation.js';
|
|
5
5
|
import { Fore } from '../fore.js';
|
|
6
|
+
import getInScopeContext from '../getInScopeContext.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* `fx-setvalue`
|
|
@@ -10,102 +11,123 @@ import { Fore } from '../fore.js';
|
|
|
10
11
|
* @customElement
|
|
11
12
|
*/
|
|
12
13
|
export default class FxSetvalue extends AbstractAction {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
super();
|
|
27
|
-
this.ref = '';
|
|
28
|
-
this.valueAttr = '';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
connectedCallback() {
|
|
32
|
-
if (super.connectedCallback) {
|
|
33
|
-
super.connectedCallback();
|
|
14
|
+
static get properties() {
|
|
15
|
+
return {
|
|
16
|
+
...super.properties,
|
|
17
|
+
ref: {
|
|
18
|
+
type: String,
|
|
19
|
+
},
|
|
20
|
+
valueAttr: {
|
|
21
|
+
type: String,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
34
24
|
}
|
|
35
25
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
this.ref = '';
|
|
29
|
+
this.valueAttr = '';
|
|
40
30
|
}
|
|
41
|
-
this.valueAttr = this.getAttribute('value');
|
|
42
|
-
}
|
|
43
31
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
connectedCallback() {
|
|
33
|
+
if (super.connectedCallback) {
|
|
34
|
+
super.connectedCallback();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (this.hasAttribute('ref')) {
|
|
38
|
+
this.ref = this.getAttribute('ref');
|
|
39
|
+
} else {
|
|
40
|
+
throw new Error('fx-setvalue must specify a "ref" attribute');
|
|
41
|
+
}
|
|
42
|
+
this.valueAttr = this.getAttribute('value');
|
|
53
43
|
}
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
|
|
45
|
+
async perform() {
|
|
46
|
+
super.perform();
|
|
47
|
+
let { value } = this;
|
|
48
|
+
if (this.valueAttr !== null) {
|
|
49
|
+
const inscopeContext = getInScopeContext(this, this.valueAttr);
|
|
50
|
+
/*
|
|
51
|
+
todo: review @martin - shouldn't we always return a string value?
|
|
52
|
+
this comes down to the question if setvalue should only allow setting of strings
|
|
53
|
+
which i tend to agree. Can't remember a case where i wanted to set an attribute
|
|
54
|
+
or element (for json wouldn't make much sense either) - for cases like that
|
|
55
|
+
fx-replace would be more appropriate.
|
|
56
|
+
|
|
57
|
+
This is of practical relevance cause currently forces to append 'text()' to value expressions
|
|
58
|
+
or getting unexpected results.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
[value] = evaluateXPath(
|
|
62
|
+
this.valueAttr,
|
|
63
|
+
inscopeContext,
|
|
64
|
+
this,
|
|
65
|
+
this.detail,
|
|
66
|
+
);
|
|
67
|
+
} else if (this.textContent !== '') {
|
|
68
|
+
value = this.textContent;
|
|
69
|
+
} else {
|
|
70
|
+
value = '';
|
|
71
|
+
}
|
|
72
|
+
if (value?.nodeType && value.nodeType === Node.ATTRIBUTE_NODE) {
|
|
73
|
+
value = value.nodeValue;
|
|
74
|
+
}
|
|
75
|
+
const mi = this.getModelItem();
|
|
76
|
+
this.setValue(mi, value);
|
|
77
|
+
// todo: check this again - logically needsUpate should be set but makes tests fail
|
|
78
|
+
// this.needsUpdate = true;
|
|
56
79
|
}
|
|
57
|
-
const mi = this.getModelItem();
|
|
58
|
-
this.setValue(mi, value);
|
|
59
|
-
// todo: check this again - logically needsUpate should be set but makes tests fail
|
|
60
|
-
// this.needsUpdate = true;
|
|
61
|
-
}
|
|
62
80
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
/**
|
|
82
|
+
* need to overwrite default dispatchExecute to do it ourselves. This is necessary for tracking control value changes
|
|
83
|
+
* which call setvalue directly without perform().
|
|
84
|
+
*/
|
|
85
|
+
dispatchExecute() {}
|
|
68
86
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
setValue(modelItem, newVal) {
|
|
88
|
+
const item = modelItem;
|
|
89
|
+
if (!item) return;
|
|
72
90
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
if (item.value !== newVal) {
|
|
92
|
+
// const path = XPathUtil.getPath(modelItem.node);
|
|
93
|
+
const path = Fore.getDomNodeIndexString(modelItem.node);
|
|
76
94
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
const ev = this.event;
|
|
96
|
+
const targetElem = this;
|
|
97
|
+
this.dispatchEvent(
|
|
98
|
+
new CustomEvent('execute-action', {
|
|
99
|
+
composed: true,
|
|
100
|
+
bubbles: true,
|
|
101
|
+
cancelable: true,
|
|
102
|
+
detail: {
|
|
103
|
+
action: targetElem,
|
|
104
|
+
event: ev,
|
|
105
|
+
value: newVal,
|
|
106
|
+
path,
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
92
110
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
if (newVal?.nodeType) {
|
|
112
|
+
if (newVal.nodeType === Node.ELEMENT_NODE) {
|
|
113
|
+
item.value = newVal;
|
|
114
|
+
}
|
|
115
|
+
if (newVal.nodeType === Node.ATTRIBUTE_NODE) {
|
|
116
|
+
item.value = newVal.getValue();
|
|
117
|
+
}
|
|
118
|
+
if (newVal.nodeType === Node.TEXT_NODE) {
|
|
119
|
+
item.value = newVal.textContent;
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
item.value = newVal;
|
|
123
|
+
item.node.textContent = newVal;
|
|
124
|
+
}
|
|
125
|
+
this.getModel().changed.push(modelItem);
|
|
126
|
+
this.needsUpdate = true;
|
|
99
127
|
}
|
|
100
|
-
} else {
|
|
101
|
-
item.value = newVal;
|
|
102
|
-
}
|
|
103
|
-
this.getModel().changed.push(modelItem);
|
|
104
|
-
this.needsUpdate = true;
|
|
105
128
|
}
|
|
106
|
-
}
|
|
107
129
|
}
|
|
108
130
|
|
|
109
131
|
if (!customElements.get('fx-setvalue')) {
|
|
110
|
-
|
|
132
|
+
window.customElements.define('fx-setvalue', FxSetvalue);
|
|
111
133
|
}
|
package/src/actions/fx-show.js
CHANGED
|
@@ -4,7 +4,9 @@ import { resolveId } from '../xpath-evaluation.js';
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* `fx-show`
|
|
7
|
-
*
|
|
7
|
+
* to show a `<dialog>` with given id.
|
|
8
|
+
*
|
|
9
|
+
*
|
|
8
10
|
*
|
|
9
11
|
* @customElement
|
|
10
12
|
* @event fx-show dispatched when dialog is shown
|
|
@@ -34,7 +36,7 @@ export class FxShow extends FxAction {
|
|
|
34
36
|
if (!targetDlg) {
|
|
35
37
|
console.error('target dialog with given id does not exist', this.dialog);
|
|
36
38
|
}
|
|
37
|
-
targetDlg.
|
|
39
|
+
targetDlg.showModal();
|
|
38
40
|
Fore.dispatch(targetDlg, 'dialog-shown', {});
|
|
39
41
|
}
|
|
40
42
|
}
|
package/src/fore.js
CHANGED
|
@@ -275,7 +275,7 @@ export class Fore {
|
|
|
275
275
|
* recursively refreshes all UI Elements.
|
|
276
276
|
*
|
|
277
277
|
* @param {HTMLElement} startElement
|
|
278
|
-
* @param {(boolean|{reason:'index-function'})} force Whether to do a forced refresh. Forced
|
|
278
|
+
* @param {(boolean|{reason:'index-function', elementLocalnamesWithChanges: string[]})} force Whether to do a forced refresh. Forced
|
|
279
279
|
* refreshes are very bad for performance, try to limit them. If the forced refresh is because index functions may change, it is better to pass the reason
|
|
280
280
|
* @returns {Promise<void>}
|
|
281
281
|
*/
|
|
@@ -300,29 +300,47 @@ export class Fore {
|
|
|
300
300
|
const { children } = startElement;
|
|
301
301
|
if (children) {
|
|
302
302
|
for (const element of Array.from(children)) {
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
if (element.nodeName.toUpperCase() === 'FX-FORE') {
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
if (Fore.isUiElement(element.nodeName) && typeof element.refresh === 'function') {
|
|
307
|
+
/**
|
|
308
|
+
* @type {import('./ForeElementMixin.js').default}
|
|
309
|
+
*/
|
|
310
|
+
const bound = element;
|
|
311
|
+
if (!force) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (force === true) {
|
|
315
|
+
// Unconditional force refresh
|
|
316
|
+
bound.refresh(force);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (typeof force !== 'object') {
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (
|
|
323
|
+
force.reason === 'index-function' &&
|
|
324
|
+
bound.dependencies.isInvalidatedByIndexFunction()
|
|
325
|
+
) {
|
|
326
|
+
bound.refresh(force);
|
|
327
|
+
continue;
|
|
305
328
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
typeof force === 'object' &&
|
|
313
|
-
force.reason === 'index-function' &&
|
|
314
|
-
element._dependencies.isInvalidatedByIndexFunction()
|
|
315
|
-
) {
|
|
316
|
-
element.refresh(force);
|
|
317
|
-
continue;
|
|
318
|
-
} else if (force === true) {
|
|
319
|
-
element.refresh(force);
|
|
320
|
-
}
|
|
321
|
-
// console.log('refreshing', element, element?.ref);
|
|
322
|
-
// console.log('refreshing ',element);
|
|
323
|
-
} else if (element.nodeName.toUpperCase() !== 'FX-MODEL') {
|
|
324
|
-
Fore.refreshChildren(element, force);
|
|
329
|
+
|
|
330
|
+
if (
|
|
331
|
+
bound.dependencies.isInvalidatedByChildlistChanges(force.elementLocalnamesWithChanges)
|
|
332
|
+
) {
|
|
333
|
+
bound.refresh(force);
|
|
334
|
+
continue;
|
|
325
335
|
}
|
|
336
|
+
|
|
337
|
+
// console.log('refreshing', element, element?.ref);
|
|
338
|
+
// console.log('refreshing ',element);
|
|
339
|
+
}
|
|
340
|
+
if (!(element.inert === true)) {
|
|
341
|
+
// testing for inert catches model and action elements and should just leave updateable html elements
|
|
342
|
+
Fore.refreshChildren(element, force);
|
|
343
|
+
}
|
|
326
344
|
}
|
|
327
345
|
}
|
|
328
346
|
resolve('done');
|
package/src/fx-bind.js
CHANGED
|
@@ -306,9 +306,9 @@ export class FxBind extends ForeElementMixin {
|
|
|
306
306
|
|
|
307
307
|
// const path = fx.evaluateXPath('path()',node);
|
|
308
308
|
// const path = this.getPath(node);
|
|
309
|
-
const
|
|
309
|
+
const instanceId = XPathUtil.resolveInstance(this, this.ref);
|
|
310
310
|
|
|
311
|
-
const path = XPathUtil.getPath(node,
|
|
311
|
+
const path = XPathUtil.getPath(node, instanceId);
|
|
312
312
|
// const shortPath = this.shortenPath(path);
|
|
313
313
|
|
|
314
314
|
// ### constructing default modelitem - will get evaluated during recalculate()
|
|
@@ -325,6 +325,7 @@ export class FxBind extends ForeElementMixin {
|
|
|
325
325
|
this.type,
|
|
326
326
|
targetNode,
|
|
327
327
|
this,
|
|
328
|
+
instanceId
|
|
328
329
|
);
|
|
329
330
|
|
|
330
331
|
const alert = this.getAlert();
|