@jinntec/fore 1.10.0 → 1.10.2
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/resources/fore.css +2 -41
- package/src/actions/abstract-action.js +51 -62
- package/src/actions/fx-call.js +9 -0
- package/src/actions/fx-delete.js +1 -1
- package/src/actions/fx-insert.js +8 -4
- package/src/actions/fx-load.js +5 -2
- package/src/actions/fx-reload.js +1 -1
- package/src/actions/fx-send.js +8 -3
- package/src/actions/fx-setfocus.js +6 -1
- package/src/actions/fx-toggle.js +1 -0
- package/src/fore.js +3 -222
- package/src/fx-bind.js +1 -1
- package/src/fx-fore.js +96 -89
- package/src/fx-model.js +31 -7
- package/src/fx-submission.js +5 -0
- package/src/tools/fx-action-log.js +1 -1
- package/src/ui/abstract-control.js +18 -39
- package/src/ui/fx-control.js +12 -12
- package/src/ui/fx-repeat-attributes.js +2 -2
- package/src/ui/fx-repeat.js +12 -1
- package/src/ui/fx-repeatitem.js +2 -8
- package/src/ui/fx-switch.js +63 -40
- package/src/ui/fx-trigger.js +3 -13
- package/src/xpath-evaluation.js +215 -83
- package/src/xpath-util.js +138 -130
package/package.json
CHANGED
package/resources/fore.css
CHANGED
|
@@ -28,7 +28,7 @@ html {
|
|
|
28
28
|
nonrelevant must always be hidden
|
|
29
29
|
*/
|
|
30
30
|
[nonrelevant] {
|
|
31
|
-
display: none
|
|
31
|
+
display: none;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
[relevant] {
|
|
@@ -41,46 +41,6 @@ fx-control[required]:after {
|
|
|
41
41
|
color: red;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
[slot=messages] {
|
|
45
|
-
margin: 0 auto;
|
|
46
|
-
width: 100%;
|
|
47
|
-
padding: 2rem 0 1rem;
|
|
48
|
-
background: white;
|
|
49
|
-
border-radius: 0.5rem;
|
|
50
|
-
position: relative;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
[slot=messages]::before {
|
|
54
|
-
content: attr(data-level);
|
|
55
|
-
padding: 0.5rem;
|
|
56
|
-
background: darkred;
|
|
57
|
-
color: white;
|
|
58
|
-
display: block;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
[slot=messages] div {
|
|
62
|
-
color: black;
|
|
63
|
-
padding: 0.25rem;
|
|
64
|
-
border: thin solid #efefef;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
[slot=messages] div::before {
|
|
68
|
-
width: 6rem;
|
|
69
|
-
display: inline-block;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
[slot=messages] div:nth-child(1)::before {
|
|
73
|
-
content: 'Id:';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
[slot=messages] div:nth-child(2)::before {
|
|
77
|
-
content: 'Path:';
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
[slot=messages] div:nth-child(3)::before {
|
|
81
|
-
content: 'Message:';
|
|
82
|
-
}
|
|
83
|
-
|
|
84
44
|
.fore-error {
|
|
85
45
|
height: 2rem;
|
|
86
46
|
background: darkred;
|
|
@@ -120,6 +80,7 @@ fx-output[readonly] img {
|
|
|
120
80
|
|
|
121
81
|
.error {
|
|
122
82
|
background: var(--paper-red-500);
|
|
83
|
+
display: flex;
|
|
123
84
|
}
|
|
124
85
|
|
|
125
86
|
fx-control, fx-trigger, .fx-checkbox {
|
|
@@ -101,8 +101,6 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
101
101
|
super();
|
|
102
102
|
this.detail = {};
|
|
103
103
|
this.needsUpdate = false;
|
|
104
|
-
|
|
105
|
-
this.changedPathsQueue = [];
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
connectedCallback() {
|
|
@@ -158,20 +156,22 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
158
156
|
}
|
|
159
157
|
}
|
|
160
158
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
message: `
|
|
159
|
+
async performSafe() {
|
|
160
|
+
try {
|
|
161
|
+
await this.perform();
|
|
162
|
+
// Return true to indicate success
|
|
163
|
+
return true;
|
|
164
|
+
} catch (error) {
|
|
165
|
+
await Fore.dispatch(this, 'error', {
|
|
166
|
+
origin: this,
|
|
167
|
+
message: `Action execution failed`,
|
|
168
|
+
expr:XPathUtil.getDocPath(this),
|
|
169
|
+
level:'Error'
|
|
170
170
|
});
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
// Return false to indicate failure. Any loops must be canceled
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* executes the action.
|
|
@@ -185,7 +185,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
185
185
|
* @param e
|
|
186
186
|
*/
|
|
187
187
|
async execute(e) {
|
|
188
|
-
|
|
188
|
+
console.log(this);
|
|
189
189
|
// console.log('execute', this.event);
|
|
190
190
|
|
|
191
191
|
|
|
@@ -210,7 +210,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
210
210
|
e.preventDefault();
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
let resolveThisEvent = () => {};
|
|
214
214
|
if (e && e.listenerPromises) {
|
|
215
215
|
e.listenerPromises.push(
|
|
216
216
|
new Promise(resolve => {
|
|
@@ -224,13 +224,13 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
224
224
|
// console.log('executing e phase', e.eventPhase);
|
|
225
225
|
if (FxFore.outermostHandler === null) {
|
|
226
226
|
// console.time('outermostHandler');
|
|
227
|
-
/*
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
*/
|
|
227
|
+
/*
|
|
228
|
+
console.info(
|
|
229
|
+
`%coutermost Action `,
|
|
230
|
+
'background:#e65100; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;',
|
|
231
|
+
this,
|
|
232
|
+
);
|
|
233
|
+
*/
|
|
234
234
|
// console.log('starting outermost handler',this);
|
|
235
235
|
FxFore.outermostHandler = this;
|
|
236
236
|
this.dispatchEvent(new CustomEvent('outermost-action-start', {
|
|
@@ -240,15 +240,15 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
240
240
|
}));
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
/*
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
*/
|
|
243
|
+
/*
|
|
244
|
+
if (FxFore.outermostHandler !== this) {
|
|
245
|
+
console.info(
|
|
246
|
+
`%cAction `,
|
|
247
|
+
'background:orange; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;',
|
|
248
|
+
this,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
*/
|
|
252
252
|
// console.log('>>> outermostHandler', FxFore.outermostHandler);
|
|
253
253
|
|
|
254
254
|
if (e) {
|
|
@@ -290,10 +290,9 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
// Perform the action once. But quit if it errored
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
293
|
+
if (!this.performSafe()) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
297
296
|
|
|
298
297
|
// Go for one more iteration
|
|
299
298
|
if (this.delay) {
|
|
@@ -308,8 +307,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
308
307
|
|
|
309
308
|
// After loop is done call actionPerformed to update the model and UI
|
|
310
309
|
await loop();
|
|
311
|
-
|
|
312
|
-
this._finalizePerform(resolveThisEvent, []);
|
|
310
|
+
this._finalizePerform(resolveThisEvent);
|
|
313
311
|
|
|
314
312
|
return;
|
|
315
313
|
}
|
|
@@ -325,28 +323,23 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
325
323
|
}
|
|
326
324
|
}
|
|
327
325
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
this._finalizePerform(resolveThisEvent, []);
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
this._finalizePerform(resolveThisEvent, result);
|
|
334
|
-
|
|
326
|
+
await this.performSafe();
|
|
327
|
+
this._finalizePerform(resolveThisEvent);
|
|
335
328
|
}
|
|
336
329
|
|
|
337
|
-
_finalizePerform(resolveThisEvent
|
|
330
|
+
_finalizePerform(resolveThisEvent) {
|
|
338
331
|
this.currentEvent = null;
|
|
339
|
-
this.actionPerformed(
|
|
332
|
+
this.actionPerformed();
|
|
340
333
|
if (FxFore.outermostHandler === this) {
|
|
341
334
|
FxFore.outermostHandler = null;
|
|
342
|
-
/*
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
*/
|
|
335
|
+
/*
|
|
336
|
+
console.info(
|
|
337
|
+
`%coutermost Action done`,
|
|
338
|
+
'background:#e65100; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;',
|
|
339
|
+
this,
|
|
340
|
+
);
|
|
341
|
+
console.timeEnd('outermostHandler');
|
|
342
|
+
*/
|
|
350
343
|
this.dispatchEvent(new CustomEvent('outermost-action-end', {
|
|
351
344
|
composed: true,
|
|
352
345
|
bubbles: true,
|
|
@@ -372,7 +365,6 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
372
365
|
this.evalInContext();
|
|
373
366
|
}
|
|
374
367
|
|
|
375
|
-
/*
|
|
376
368
|
this.dispatchEvent(
|
|
377
369
|
new CustomEvent('execute-action', {
|
|
378
370
|
composed: true,
|
|
@@ -381,14 +373,13 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
381
373
|
detail: {action: this, event: this.event},
|
|
382
374
|
}),
|
|
383
375
|
);
|
|
384
|
-
*/
|
|
385
376
|
|
|
386
377
|
}
|
|
387
378
|
|
|
388
379
|
/**
|
|
389
380
|
* calls the update cycle if action signalled that update is needed.
|
|
390
381
|
*/
|
|
391
|
-
actionPerformed(
|
|
382
|
+
actionPerformed() {
|
|
392
383
|
const model = this.getModel();
|
|
393
384
|
if (!model) {
|
|
394
385
|
return;
|
|
@@ -413,15 +404,13 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
413
404
|
// console.log('running update cycle for outermostHandler', this);
|
|
414
405
|
model.recalculate();
|
|
415
406
|
model.revalidate();
|
|
416
|
-
model.parentNode.refresh(
|
|
417
|
-
this.changedPathsQueue = [];
|
|
407
|
+
model.parentNode.refresh(true);
|
|
418
408
|
this.dispatchActionPerformed();
|
|
419
409
|
} else if (this.needsUpdate) {
|
|
420
410
|
// console.log('Update delayed!');
|
|
421
411
|
// We need an update, but the outermost action handler is not done yet. Make this clear!
|
|
422
412
|
// console.log('running actionperformed on', this, ' to be updated by ', FxFore.outermostHandler);
|
|
423
413
|
FxFore.outermostHandler.needsUpdate = true;
|
|
424
|
-
FxFore.outermostHandler.changedPathsQueue.push(...changedPaths);
|
|
425
414
|
}
|
|
426
415
|
|
|
427
416
|
// console.log('running actionperformed on', this, ' outermostHandler', FxFore.outermostHandler);
|
package/src/actions/fx-call.js
CHANGED
|
@@ -3,6 +3,7 @@ import {AbstractAction} from './abstract-action.js';
|
|
|
3
3
|
import {evaluateXPath, evaluateXPathToString} from "../xpath-evaluation.js";
|
|
4
4
|
import {Fore} from "../fore";
|
|
5
5
|
import getInScopeContext from "../getInScopeContext";
|
|
6
|
+
import {XPathUtil} from "../xpath-util.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* `fx-call`
|
|
@@ -60,7 +61,15 @@ export default class FxCall extends AbstractAction {
|
|
|
60
61
|
const action = document.querySelector(`#${this.action}`);
|
|
61
62
|
if(action){
|
|
62
63
|
await action.perform();
|
|
64
|
+
}else{
|
|
65
|
+
Fore.dispatch(this, 'error', {
|
|
66
|
+
origin: this,
|
|
67
|
+
message: `Action '${this.action}' not found`,
|
|
68
|
+
expr:XPathUtil.getDocPath(this),
|
|
69
|
+
level:'Error'
|
|
70
|
+
});
|
|
63
71
|
}
|
|
72
|
+
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
_callFunction(){
|
package/src/actions/fx-delete.js
CHANGED
|
@@ -35,7 +35,7 @@ class FxDelete extends AbstractAction {
|
|
|
35
35
|
|
|
36
36
|
// console.log('delete nodeset ', this.nodeset);
|
|
37
37
|
|
|
38
|
-
const instanceId = XPathUtil.resolveInstance(this);
|
|
38
|
+
const instanceId = XPathUtil.resolveInstance(this, this.ref);
|
|
39
39
|
const instance = this.getModel().getInstance(instanceId);
|
|
40
40
|
|
|
41
41
|
// const path = instance && this.nodeset.length !== 0 ? evaluateXPathToString('path()', this.nodeset[0], instance) : '';
|
package/src/actions/fx-insert.js
CHANGED
|
@@ -228,11 +228,14 @@ export class FxInsert extends AbstractAction {
|
|
|
228
228
|
// console.log('instance ', this.getModel().getDefaultContext());
|
|
229
229
|
// Fore.dispatch()
|
|
230
230
|
|
|
231
|
-
const instanceId = XPathUtil.resolveInstance(this, this.getAttribute('context'));
|
|
231
|
+
// const instanceId = XPathUtil.resolveInstance(this, this.getAttribute('context'));
|
|
232
|
+
const instanceId = XPathUtil.resolveInstance(this, this.ref);
|
|
232
233
|
const inst = this.getModel().getInstance(instanceId);
|
|
233
234
|
// console.log('<<<<<<< resolved instance', inst);
|
|
234
235
|
// Note: the parent to insert under is always the parent of the inserted node. The 'context' is not always the parent if the sequence is empty, or the position is different
|
|
235
|
-
const xpath = XPathUtil.getPath(originSequenceClone.parentNode, instanceId);
|
|
236
|
+
// const xpath = XPathUtil.getPath(originSequenceClone.parentNode, instanceId);
|
|
237
|
+
const xpath = XPathUtil.getPath(insertLocationNode.parentNode, instanceId);
|
|
238
|
+
|
|
236
239
|
|
|
237
240
|
|
|
238
241
|
const path = Fore.getDomNodeIndexString(originSequenceClone);
|
|
@@ -281,8 +284,9 @@ export class FxInsert extends AbstractAction {
|
|
|
281
284
|
}
|
|
282
285
|
|
|
283
286
|
actionPerformed(changedPaths) {
|
|
284
|
-
//
|
|
285
|
-
|
|
287
|
+
// ### make sure the necessary modelItems will get created
|
|
288
|
+
this.getModel().rebuild();
|
|
289
|
+
super.actionPerformed();
|
|
286
290
|
}
|
|
287
291
|
|
|
288
292
|
/**
|
package/src/actions/fx-load.js
CHANGED
|
@@ -113,11 +113,14 @@ class FxLoad extends AbstractAction {
|
|
|
113
113
|
// for authoring errors we log errors directly to DOM
|
|
114
114
|
|
|
115
115
|
this.dispatchEvent(
|
|
116
|
-
new CustomEvent('
|
|
116
|
+
new CustomEvent('error', {
|
|
117
117
|
composed: false,
|
|
118
118
|
bubbles: true,
|
|
119
119
|
cancelable:true,
|
|
120
|
-
detail: {
|
|
120
|
+
detail: {
|
|
121
|
+
origin:this,
|
|
122
|
+
message: `neither template element nor Url was specified.`,
|
|
123
|
+
level:'Error'},
|
|
121
124
|
}),
|
|
122
125
|
);
|
|
123
126
|
return;
|
package/src/actions/fx-reload.js
CHANGED
package/src/actions/fx-send.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import '../fx-model.js';
|
|
2
2
|
import '../fx-submission.js';
|
|
3
3
|
import { AbstractAction } from './abstract-action.js';
|
|
4
|
+
import {XPathUtil} from "../xpath-util.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* `fx-send` - finds and activates a `fx-submission` element.
|
|
@@ -45,16 +46,20 @@ class FxSend extends AbstractAction {
|
|
|
45
46
|
new CustomEvent('error', {
|
|
46
47
|
composed: true,
|
|
47
48
|
bubbles: true,
|
|
48
|
-
detail: { message: `fx-submission element with id: '${this.submission}' not found` },
|
|
49
|
+
detail: { message: `fx-submission element with id: '${this.submission}' not found - ${XPathUtil.getDocPath(this)}` },
|
|
49
50
|
}),
|
|
50
51
|
);
|
|
51
52
|
*/
|
|
52
53
|
this.dispatchEvent(
|
|
53
|
-
new CustomEvent('
|
|
54
|
+
new CustomEvent('error', {
|
|
54
55
|
composed: false,
|
|
55
56
|
bubbles: true,
|
|
56
57
|
cancelable:true,
|
|
57
|
-
detail: { id:this.id,
|
|
58
|
+
detail: { id:this.id,
|
|
59
|
+
origin: this,
|
|
60
|
+
message: `<fx-submission id="${this.submission}"> not found`,
|
|
61
|
+
expr:XPathUtil.getDocPath(this),
|
|
62
|
+
level:'Error'},
|
|
58
63
|
}),
|
|
59
64
|
);
|
|
60
65
|
return;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {AbstractAction} from "./abstract-action.js";
|
|
2
|
+
import {Fore} from "../fore";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* `fx-setfocus`
|
|
@@ -32,7 +33,11 @@ export class FxSetfocus extends AbstractAction {
|
|
|
32
33
|
let targetElement = document.querySelector(selector);
|
|
33
34
|
|
|
34
35
|
if(!targetElement) {
|
|
35
|
-
|
|
36
|
+
Fore.dispatch(this, 'error', {
|
|
37
|
+
origin: this,
|
|
38
|
+
message: `Instance '${this.control}' not found`,
|
|
39
|
+
level:'Error'
|
|
40
|
+
});
|
|
36
41
|
return;
|
|
37
42
|
}
|
|
38
43
|
|
package/src/actions/fx-toggle.js
CHANGED
|
@@ -23,6 +23,7 @@ class FxToggle extends AbstractAction {
|
|
|
23
23
|
super.perform();
|
|
24
24
|
if (this.case) {
|
|
25
25
|
const ownerForm = this.getOwnerForm();
|
|
26
|
+
// todo: id resolution!!!
|
|
26
27
|
const caseElement = ownerForm.querySelector(`#${this.case}`);
|
|
27
28
|
if(!caseElement){
|
|
28
29
|
Fore.dispatch(this, 'error', { message: `fx-case id not found: ${this.case}` });
|
package/src/fore.js
CHANGED
|
@@ -18,228 +18,6 @@ export class Fore {
|
|
|
18
18
|
|
|
19
19
|
static TYPE_DEFAULT = 'xs:string';
|
|
20
20
|
|
|
21
|
-
/**
|
|
22
|
-
* recursively walks along a template instance that contains all nodes relevant for editing and
|
|
23
|
-
* applying all nodes being present in partial instance onto it.
|
|
24
|
-
*
|
|
25
|
-
* @param start
|
|
26
|
-
* @param partial
|
|
27
|
-
* @returns {*}
|
|
28
|
-
* @private
|
|
29
|
-
*/
|
|
30
|
-
static combine(start, partial, foreElement,expr){
|
|
31
|
-
if(!start) return;
|
|
32
|
-
|
|
33
|
-
const appended = false;
|
|
34
|
-
// ### get the path of the current element
|
|
35
|
-
let path = evaluateXPath('path()',start,foreElement)[0];
|
|
36
|
-
if(expr){
|
|
37
|
-
path = expr;
|
|
38
|
-
}
|
|
39
|
-
// const attrMap = new Map();
|
|
40
|
-
console.log('########process path', XPathUtil.shortenPath(path));
|
|
41
|
-
const predicates = Fore.buildPredicates(start);
|
|
42
|
-
// console.log('########process search', path);
|
|
43
|
-
// ### search the path in the partial instance
|
|
44
|
-
const toMerge = evaluateXPathToFirstNode( path,partial,foreElement);
|
|
45
|
-
if(expr){
|
|
46
|
-
console.log('skipped one - new toMerge', toMerge);
|
|
47
|
-
}
|
|
48
|
-
// console.log('tomerge node', toMerge);
|
|
49
|
-
// if(toMerge.length === 1){}
|
|
50
|
-
if(toMerge){
|
|
51
|
-
// console.log('merging nodes', toMerge);
|
|
52
|
-
const mergeAttrs = Fore.buildPredicates(toMerge);
|
|
53
|
-
if(predicates === mergeAttrs) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// console.log('####### attr maps', attrMap, toMergeAttrMap);
|
|
57
|
-
// console.log('########process merge attrs', mergeAttrs);
|
|
58
|
-
if(start.getAttribute('type') !== toMerge.getAttribute('type') ){
|
|
59
|
-
console.log('###### element type attr not matching', start, toMerge);
|
|
60
|
-
const nextSibling = start.nextElementSibling;
|
|
61
|
-
if(nextSibling && nextSibling.nodeName === start.nodeName){
|
|
62
|
-
console.log('nextSibling', nextSibling, XPathUtil.shortenPath(path));
|
|
63
|
-
console.log('start', start, XPathUtil.shortenPath(path));
|
|
64
|
-
Fore.combine(start,partial,foreElement,path);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ### iterate the attributes of the template node
|
|
69
|
-
// if(attrMap === toMergeAttrMap){
|
|
70
|
-
// if(start.attributes){
|
|
71
|
-
Array.from(start.attributes).forEach(attr => {
|
|
72
|
-
// ### if the template attribute has a matching attribute in partial...
|
|
73
|
-
if (toMerge.hasAttribute(attr.nodeName)) {
|
|
74
|
-
if (attr.nodeName !== 'xmlns') {
|
|
75
|
-
// console.log('overwrite attr', attr);
|
|
76
|
-
const toMergeAttr = toMerge.getAttribute(attr.nodeName);
|
|
77
|
-
// if (attr.nodeValue !== toMergeAttr.nodeValue) {
|
|
78
|
-
// ### apply the attribute value from partial to template
|
|
79
|
-
if(toMergeAttr){
|
|
80
|
-
start.setAttribute(attr.nodeName, toMergeAttr)
|
|
81
|
-
}
|
|
82
|
-
// }
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
// }
|
|
87
|
-
}else{
|
|
88
|
-
console.log('###### element in template but not in partial',start);
|
|
89
|
-
const nextSibling = start.nextElementSibling;
|
|
90
|
-
if(nextSibling && nextSibling.nodeName === start.nodeName){
|
|
91
|
-
Fore.combine(nextSibling,partial,foreElement,path);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// ### if we don't have children we still might have text
|
|
95
|
-
if(toMerge.children.length === 0){
|
|
96
|
-
const toMergeText = toMerge.textContent;
|
|
97
|
-
if(toMergeText){
|
|
98
|
-
start.textContent = toMergeText;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ### if the template node does not have children but the partial has then copy them over
|
|
103
|
-
if(start.children.length === 0 && toMerge.children.length !== 0){
|
|
104
|
-
const mergeChildren = Array.from(toMerge.children);
|
|
105
|
-
mergeChildren.forEach(child => {
|
|
106
|
-
start.append(child);
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ### recurse
|
|
112
|
-
if(start.children){
|
|
113
|
-
Array.from(start.children).forEach(element => {
|
|
114
|
-
/*
|
|
115
|
-
console.log('stepping into element', element);
|
|
116
|
-
if(element.getAttribute('type') !== toMerge.getAttribute('type')){
|
|
117
|
-
// console.log('###### element in template but not in partial');
|
|
118
|
-
// const nextSibling = start.nextElementSibling;
|
|
119
|
-
const nextSibling = element.nextElementSibling;
|
|
120
|
-
if(nextSibling && nextSibling.nodeName === toMerge.nodeName){
|
|
121
|
-
console.log('nextSibling', nextSibling, XPathUtil.shortenPath(path));
|
|
122
|
-
Fore.combine(nextSibling,partial,foreElement,path);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
*/
|
|
126
|
-
return Fore.combine(element, partial,foreElement,null);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
return start;
|
|
132
|
-
}
|
|
133
|
-
/*
|
|
134
|
-
static combine(start, partial, foreElement,expr){
|
|
135
|
-
if(!start) return;
|
|
136
|
-
// ### get the path of the current element
|
|
137
|
-
let path = evaluateXPath('path()',start,foreElement)[0];
|
|
138
|
-
if(expr){
|
|
139
|
-
path = expr;
|
|
140
|
-
}
|
|
141
|
-
// const attrMap = new Map();
|
|
142
|
-
console.log('########process path', XPathUtil.shortenPath(path));
|
|
143
|
-
const predicates = Fore.buildPredicates(start);
|
|
144
|
-
/!*
|
|
145
|
-
if(predicates){
|
|
146
|
-
path = path.substring(1, path.lastIndexOf('['));
|
|
147
|
-
}
|
|
148
|
-
path += Fore.buildPredicates(start);
|
|
149
|
-
*!/
|
|
150
|
-
// console.log('########process search', path);
|
|
151
|
-
// ### search the path in the partial instance
|
|
152
|
-
const toMerge = evaluateXPathToFirstNode( path,partial,foreElement);
|
|
153
|
-
|
|
154
|
-
// console.log('tomerge node', toMerge);
|
|
155
|
-
// if(toMerge.length === 1){}
|
|
156
|
-
if(toMerge){
|
|
157
|
-
// console.log('merging nodes', toMerge);
|
|
158
|
-
const mergeAttrs = Fore.buildPredicates(toMerge);
|
|
159
|
-
if(predicates === mergeAttrs) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// console.log('####### attr maps', attrMap, toMergeAttrMap);
|
|
163
|
-
// console.log('########process merge attrs', mergeAttrs);
|
|
164
|
-
/!*
|
|
165
|
-
if(toMerge.getAttribute('type') !== start.getAttribute('type')){
|
|
166
|
-
// console.log('###### element in template but not in partial');
|
|
167
|
-
// const nextSibling = start.nextElementSibling;
|
|
168
|
-
const nextSibling = start.nextElementSibling;
|
|
169
|
-
if(nextSibling && nextSibling.nodeName === start.nodeName){
|
|
170
|
-
console.log('nextSibling', nextSibling, XPathUtil.shortenPath(path));
|
|
171
|
-
Fore.combine(nextSibling,partial,foreElement,path);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
*!/
|
|
175
|
-
|
|
176
|
-
// ### iterate the attributes of the template node
|
|
177
|
-
// if(attrMap === toMergeAttrMap){
|
|
178
|
-
// if(start.attributes){
|
|
179
|
-
Array.from(start.attributes).forEach(attr => {
|
|
180
|
-
// ### if the template attribute has a matching attribute in partial...
|
|
181
|
-
if (toMerge.hasAttribute(attr.nodeName)) {
|
|
182
|
-
if (attr.nodeName !== 'xmlns') {
|
|
183
|
-
// console.log('overwrite attr', attr);
|
|
184
|
-
const toMergeAttr = toMerge.getAttribute(attr.nodeName);
|
|
185
|
-
// if (attr.nodeValue !== toMergeAttr.nodeValue) {
|
|
186
|
-
// ### apply the attribute value from partial to template
|
|
187
|
-
if(toMergeAttr){
|
|
188
|
-
start.setAttribute(attr.nodeName, toMergeAttr)
|
|
189
|
-
}
|
|
190
|
-
// }
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
// }
|
|
195
|
-
}else{
|
|
196
|
-
console.log('###### element in template but not in partial',start);
|
|
197
|
-
const nextSibling = start.nextElementSibling;
|
|
198
|
-
if(nextSibling && nextSibling.nodeName === start.nodeName){
|
|
199
|
-
Fore.combine(nextSibling,partial,foreElement,path);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
// ### if we don't have children we still might have text
|
|
203
|
-
if(toMerge.children.length === 0){
|
|
204
|
-
const toMergeText = toMerge.textContent;
|
|
205
|
-
if(toMergeText){
|
|
206
|
-
start.textContent = toMergeText;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// ### if the template node does not have children but the partial has then copy them over
|
|
211
|
-
if(start.children.length === 0 && toMerge.children.length !== 0){
|
|
212
|
-
const mergeChildren = Array.from(toMerge.children);
|
|
213
|
-
mergeChildren.forEach(child => {
|
|
214
|
-
start.append(child);
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// ### recurse
|
|
220
|
-
if(start.children){
|
|
221
|
-
Array.from(start.children).forEach(element => {
|
|
222
|
-
/!*
|
|
223
|
-
console.log('stepping into element', element);
|
|
224
|
-
if(element.getAttribute('type') !== toMerge.getAttribute('type')){
|
|
225
|
-
// console.log('###### element in template but not in partial');
|
|
226
|
-
// const nextSibling = start.nextElementSibling;
|
|
227
|
-
const nextSibling = element.nextElementSibling;
|
|
228
|
-
if(nextSibling && nextSibling.nodeName === toMerge.nodeName){
|
|
229
|
-
console.log('nextSibling', nextSibling, XPathUtil.shortenPath(path));
|
|
230
|
-
Fore.combine(nextSibling,partial,foreElement,path);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
*!/
|
|
234
|
-
return Fore.combine(element, partial,foreElement);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
return start;
|
|
240
|
-
}
|
|
241
|
-
*/
|
|
242
|
-
|
|
243
21
|
static buildPredicates(node){
|
|
244
22
|
let attrPredicate='';
|
|
245
23
|
Array.from(node.attributes).forEach(attr =>{
|
|
@@ -686,6 +464,9 @@ export class Fore {
|
|
|
686
464
|
}
|
|
687
465
|
}
|
|
688
466
|
|
|
467
|
+
static stringifiedComponent(element){
|
|
468
|
+
return `<${element.localName} ${Array.from(element.attributes).map(attr=>`${attr.name}="${attr.value}"`).join(' ')}>…</${element.localName}>`;
|
|
469
|
+
}
|
|
689
470
|
static async loadForeFromUrl(hostElement, url) {
|
|
690
471
|
// console.log('########## loading Fore from ', this.src, '##########');
|
|
691
472
|
await fetch(url, {
|