@jinntec/fore 1.8.0 → 1.10.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/README.md +17 -0
- 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 +7 -2
- package/resources/fore.css +4 -0
- package/src/DependencyNotifyingDomFacade.js +2 -2
- package/src/actions/abstract-action.js +24 -11
- package/src/actions/fx-insert.js +13 -6
- package/src/actions/fx-setfocus.js +1 -1
- package/src/fore.js +238 -1
- package/src/fx-bind.js +12 -6
- package/src/fx-fore.js +86 -9
- package/src/fx-instance.js +9 -3
- package/src/fx-model.js +3 -1
- package/src/fx-submission.js +46 -157
- package/src/tools/adi.js +16 -7
- package/src/tools/fx-action-log.js +1 -1
- package/src/ui/abstract-control.js +8 -7
- package/src/ui/fx-control.js +18 -7
- package/src/ui/fx-dialog.js +2 -0
- package/src/ui/fx-group.js +4 -1
- package/src/ui/fx-repeat-attributes.js +4 -1
- package/src/ui/fx-repeat.js +11 -2
- package/src/ui/fx-repeatitem.js +5 -3
- package/src/ui/fx-trigger.js +3 -1
- package/src/xpath-evaluation.js +101 -4
- package/src/xpath-util.js +9 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jinntec/fore",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Fore - declarative user interfaces in plain HTML",
|
|
5
5
|
"module": "./index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"fontoxpath": "^3.30.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
+
"@types/cypress": "^1.1.3",
|
|
37
38
|
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
|
38
39
|
"@open-wc/building-rollup": "^2.0.1",
|
|
39
40
|
"@open-wc/eslint-config": "^7.0.0",
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
"@rollup/plugin-strip": "^2.1.0",
|
|
48
49
|
"@skypack/package-check": "^0.2.2",
|
|
49
50
|
"@webcomponents/webcomponentsjs": "^2.6.0",
|
|
51
|
+
"cypress": "^13.3.0",
|
|
50
52
|
"deepmerge": "^4.2.2",
|
|
51
53
|
"es-dev-server": "^2.1.0",
|
|
52
54
|
"eslint": "^8.16.0",
|
|
@@ -82,7 +84,10 @@
|
|
|
82
84
|
"start:build": "cd dist && es-dev-server --open",
|
|
83
85
|
"build": "rimraf dist && rollup -c rollup.config.js",
|
|
84
86
|
"start": "es-dev-server --app-index doc/index.html --node-resolve --watch --open",
|
|
85
|
-
"
|
|
87
|
+
"preversion": "npm run test",
|
|
88
|
+
"prepare": "npm run build",
|
|
89
|
+
"install-demos": "npm i && cd demo && npm i",
|
|
90
|
+
"start-cypress": "es-dev-server --app-index doc/index.html --node-resolve"
|
|
86
91
|
},
|
|
87
92
|
"keywords": [
|
|
88
93
|
"Fore",
|
package/resources/fore.css
CHANGED
|
@@ -114,7 +114,7 @@ export class DependencyNotifyingDomFacade {
|
|
|
114
114
|
// eslint-disable-next-line class-methods-use-this
|
|
115
115
|
getNextSibling(node, bucket) {
|
|
116
116
|
for (let sibling = node.nextSibling; sibling; sibling = sibling.nextSibling) {
|
|
117
|
-
if (!getBucketsForNode(sibling).includes(bucket)) {
|
|
117
|
+
if (bucket && !getBucketsForNode(sibling).includes(bucket)) {
|
|
118
118
|
// eslint-disable-next-line no-continue
|
|
119
119
|
continue;
|
|
120
120
|
}
|
|
@@ -149,7 +149,7 @@ export class DependencyNotifyingDomFacade {
|
|
|
149
149
|
previousSibling;
|
|
150
150
|
previousSibling = previousSibling.previousSibling
|
|
151
151
|
) {
|
|
152
|
-
if (!getBucketsForNode(previousSibling).includes(bucket)) {
|
|
152
|
+
if (bucket && !getBucketsForNode(previousSibling).includes(bucket)) {
|
|
153
153
|
// eslint-disable-next-line no-continue
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
@@ -101,6 +101,8 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
101
101
|
super();
|
|
102
102
|
this.detail = {};
|
|
103
103
|
this.needsUpdate = false;
|
|
104
|
+
|
|
105
|
+
this.changedPathsQueue = [];
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
connectedCallback() {
|
|
@@ -158,9 +160,9 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
158
160
|
|
|
159
161
|
async performSafe() {
|
|
160
162
|
try {
|
|
161
|
-
await this.perform();
|
|
162
|
-
// Return
|
|
163
|
-
return
|
|
163
|
+
const changedPaths = await this.perform();
|
|
164
|
+
// Return truthy to indicate success
|
|
165
|
+
return changedPaths;
|
|
164
166
|
} catch (error) {
|
|
165
167
|
const stringifiedComponent = `<${this.localName} ${Array.from(this.attributes).map(attr=>`${attr.name}="${attr.value}"`).join(' ')}>…</${this.localName}>`;
|
|
166
168
|
await Fore.dispatch(this, 'error', {
|
|
@@ -288,7 +290,8 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
288
290
|
}
|
|
289
291
|
|
|
290
292
|
// Perform the action once. But quit if it errored
|
|
291
|
-
|
|
293
|
+
const result = this.performSafe();
|
|
294
|
+
if (!result) {
|
|
292
295
|
return;
|
|
293
296
|
}
|
|
294
297
|
|
|
@@ -305,7 +308,8 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
305
308
|
|
|
306
309
|
// After loop is done call actionPerformed to update the model and UI
|
|
307
310
|
await loop();
|
|
308
|
-
|
|
311
|
+
// TODO: pass the result(s)
|
|
312
|
+
this._finalizePerform(resolveThisEvent, []);
|
|
309
313
|
|
|
310
314
|
return;
|
|
311
315
|
}
|
|
@@ -321,13 +325,18 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
321
325
|
}
|
|
322
326
|
}
|
|
323
327
|
|
|
324
|
-
await this.performSafe();
|
|
325
|
-
|
|
328
|
+
const result = await this.performSafe();
|
|
329
|
+
if (!result) {
|
|
330
|
+
this._finalizePerform(resolveThisEvent, []);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
this._finalizePerform(resolveThisEvent, result);
|
|
334
|
+
|
|
326
335
|
}
|
|
327
336
|
|
|
328
|
-
_finalizePerform(resolveThisEvent) {
|
|
337
|
+
_finalizePerform(resolveThisEvent, changedPaths) {
|
|
329
338
|
this.currentEvent = null;
|
|
330
|
-
this.actionPerformed();
|
|
339
|
+
this.actionPerformed(changedPaths);
|
|
331
340
|
if (FxFore.outermostHandler === this) {
|
|
332
341
|
FxFore.outermostHandler = null;
|
|
333
342
|
/*
|
|
@@ -363,6 +372,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
363
372
|
this.evalInContext();
|
|
364
373
|
}
|
|
365
374
|
|
|
375
|
+
/*
|
|
366
376
|
this.dispatchEvent(
|
|
367
377
|
new CustomEvent('execute-action', {
|
|
368
378
|
composed: true,
|
|
@@ -371,13 +381,14 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
371
381
|
detail: {action: this, event: this.event},
|
|
372
382
|
}),
|
|
373
383
|
);
|
|
384
|
+
*/
|
|
374
385
|
|
|
375
386
|
}
|
|
376
387
|
|
|
377
388
|
/**
|
|
378
389
|
* calls the update cycle if action signalled that update is needed.
|
|
379
390
|
*/
|
|
380
|
-
actionPerformed() {
|
|
391
|
+
actionPerformed(changedPaths = []) {
|
|
381
392
|
const model = this.getModel();
|
|
382
393
|
if (!model) {
|
|
383
394
|
return;
|
|
@@ -402,13 +413,15 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
402
413
|
// console.log('running update cycle for outermostHandler', this);
|
|
403
414
|
model.recalculate();
|
|
404
415
|
model.revalidate();
|
|
405
|
-
model.parentNode.refresh(
|
|
416
|
+
model.parentNode.refresh(false, [...this.changedPathsQueue, ...changedPaths]);
|
|
417
|
+
this.changedPathsQueue = [];
|
|
406
418
|
this.dispatchActionPerformed();
|
|
407
419
|
} else if (this.needsUpdate) {
|
|
408
420
|
// console.log('Update delayed!');
|
|
409
421
|
// We need an update, but the outermost action handler is not done yet. Make this clear!
|
|
410
422
|
// console.log('running actionperformed on', this, ' to be updated by ', FxFore.outermostHandler);
|
|
411
423
|
FxFore.outermostHandler.needsUpdate = true;
|
|
424
|
+
FxFore.outermostHandler.changedPathsQueue.push(...changedPaths);
|
|
412
425
|
}
|
|
413
426
|
|
|
414
427
|
// console.log('running actionperformed on', this, ' outermostHandler', FxFore.outermostHandler);
|
package/src/actions/fx-insert.js
CHANGED
|
@@ -221,14 +221,19 @@ export class FxInsert extends AbstractAction {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
|
+
// instance('default')/items/item[index()]
|
|
224
225
|
|
|
225
226
|
// console.log('insert context item ', insertLocationNode);
|
|
226
227
|
// console.log('parent ', insertLocationNode.parentNode);
|
|
227
228
|
// console.log('instance ', this.getModel().getDefaultContext());
|
|
228
229
|
// Fore.dispatch()
|
|
229
230
|
|
|
230
|
-
|
|
231
|
-
|
|
231
|
+
const instanceId = XPathUtil.resolveInstance(this, this.getAttribute('context'));
|
|
232
|
+
const inst = this.getModel().getInstance(instanceId);
|
|
233
|
+
// console.log('<<<<<<< resolved instance', inst);
|
|
234
|
+
// 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
|
+
|
|
232
237
|
|
|
233
238
|
const path = Fore.getDomNodeIndexString(originSequenceClone);
|
|
234
239
|
this.dispatchEvent(
|
|
@@ -259,7 +264,9 @@ export class FxInsert extends AbstractAction {
|
|
|
259
264
|
}),
|
|
260
265
|
);
|
|
261
266
|
|
|
262
|
-
|
|
267
|
+
this.needsUpdate = true;
|
|
268
|
+
console.log('Changed!', xpath)
|
|
269
|
+
return [xpath];
|
|
263
270
|
}
|
|
264
271
|
|
|
265
272
|
// eslint-disable-next-line class-methods-use-this
|
|
@@ -273,9 +280,9 @@ export class FxInsert extends AbstractAction {
|
|
|
273
280
|
return null;
|
|
274
281
|
}
|
|
275
282
|
|
|
276
|
-
actionPerformed() {
|
|
277
|
-
this.getModel().rebuild();
|
|
278
|
-
super.actionPerformed();
|
|
283
|
+
actionPerformed(changedPaths) {
|
|
284
|
+
// this.getModel().rebuild();
|
|
285
|
+
super.actionPerformed(changedPaths);
|
|
279
286
|
}
|
|
280
287
|
|
|
281
288
|
/**
|
package/src/fore.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import getInScopeContext from "./getInScopeContext.js";
|
|
2
|
-
import {evaluateXPathToString} from "./xpath-evaluation.js";
|
|
2
|
+
import {evaluateXPath, evaluateXPathToFirstNode, evaluateXPathToString, evaluateXPathToNodes} from "./xpath-evaluation.js";
|
|
3
3
|
import { XPathUtil } from "./xpath-util.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -18,6 +18,243 @@ 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
|
+
static buildPredicates(node){
|
|
244
|
+
let attrPredicate='';
|
|
245
|
+
Array.from(node.attributes).forEach(attr =>{
|
|
246
|
+
// attrMap.set(attr.nodeName,attr.nodeValue);
|
|
247
|
+
// if(attr.nodeName !== 'xmlns'){
|
|
248
|
+
// if(attr.nodeValue !== ''){
|
|
249
|
+
// attrPredicate += `[@${attr.nodeName}='${attr.nodeValue}']`;
|
|
250
|
+
// }else{
|
|
251
|
+
attrPredicate += `[@${attr.nodeName}]`;
|
|
252
|
+
// }
|
|
253
|
+
// }
|
|
254
|
+
});
|
|
255
|
+
return attrPredicate
|
|
256
|
+
}
|
|
257
|
+
|
|
21
258
|
|
|
22
259
|
/**
|
|
23
260
|
* returns true if target element is the widget itself or some element within the widget.
|
package/src/fx-bind.js
CHANGED
|
@@ -79,8 +79,10 @@ export class FxBind extends foreElementMixin(HTMLElement) {
|
|
|
79
79
|
|
|
80
80
|
_buildBindGraph() {
|
|
81
81
|
if (this.bindType === 'xml') {
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
this.nodeset.forEach(node => {
|
|
83
|
+
const instance = XPathUtil.resolveInstance(this);
|
|
84
|
+
|
|
85
|
+
const path = XPathUtil.getPath(node, instance);
|
|
84
86
|
this.model.mainGraph.addNode(path, node);
|
|
85
87
|
|
|
86
88
|
/* ### catching references in the 'ref' itself...
|
|
@@ -156,8 +158,10 @@ export class FxBind extends foreElementMixin(HTMLElement) {
|
|
|
156
158
|
if (!this.model.mainGraph.hasNode(nodeHash)) {
|
|
157
159
|
this.model.mainGraph.addNode(nodeHash, node);
|
|
158
160
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
refs.forEach(ref => {
|
|
162
|
+
const instance = XPathUtil.resolveInstance(this, path);
|
|
163
|
+
|
|
164
|
+
const otherPath = XPathUtil.getPath(ref, instance);
|
|
161
165
|
// console.log('otherPath', otherPath)
|
|
162
166
|
|
|
163
167
|
// todo: nasty hack to prevent duplicate pathes like 'a[1]' and 'a[1]/text()[1]' to end up as separate nodes in the graph
|
|
@@ -301,8 +305,10 @@ export class FxBind extends foreElementMixin(HTMLElement) {
|
|
|
301
305
|
const targetNode = node;
|
|
302
306
|
|
|
303
307
|
// const path = fx.evaluateXPath('path()',node);
|
|
304
|
-
|
|
305
|
-
|
|
308
|
+
// const path = this.getPath(node);
|
|
309
|
+
const instance = XPathUtil.resolveInstance(this, this.ref);
|
|
310
|
+
|
|
311
|
+
const path = XPathUtil.getPath(node, instance);
|
|
306
312
|
// const shortPath = this.shortenPath(path);
|
|
307
313
|
|
|
308
314
|
// ### constructing default modelitem - will get evaluated during recalculate()
|