@jinntec/fore 2.6.0 → 2.7.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 +4470 -2643
- package/dist/fore.js +4415 -2620
- package/index.js +2 -0
- package/package.json +10 -4
- package/resources/fore.css +2 -6
- package/src/DependencyNotifyingDomFacade.js +27 -21
- package/src/ForeElementMixin.js +282 -277
- package/src/actions/abstract-action.js +7 -12
- package/src/actions/fx-append.js +23 -2
- package/src/actions/fx-call.js +2 -2
- package/src/actions/fx-delete.js +54 -29
- package/src/actions/fx-insert.js +23 -15
- package/src/actions/fx-refresh.js +15 -5
- package/src/actions/fx-replace.js +18 -3
- package/src/actions/fx-reset.js +6 -0
- package/src/actions/fx-send.js +10 -7
- package/src/actions/fx-setattribute.js +12 -0
- package/src/actions/fx-setfocus.js +11 -8
- package/src/actions/fx-setvalue.js +93 -93
- package/src/actions/fx-toggle.js +1 -1
- package/src/extract-predicate-deps.js +57 -0
- package/src/extractPredicateDependencies.js +36 -0
- package/src/fore.js +41 -16
- package/src/fx-bind.js +128 -23
- package/src/fx-connection.js +24 -7
- package/src/fx-fore.js +506 -259
- package/src/fx-instance.js +9 -11
- package/src/fx-model.js +154 -65
- package/src/fx-submission.js +19 -30
- package/src/fx-var.js +5 -0
- package/src/getInScopeContext.js +7 -8
- package/src/modelitem.js +247 -112
- package/src/tools/fx-action-log.js +21 -19
- package/src/tools/fx-log-settings.js +4 -2
- package/src/ui/TemplateExpression.js +12 -0
- package/src/ui/UIElement.js +125 -10
- package/src/ui/abstract-control.js +5 -0
- package/src/ui/fx-case.js +15 -3
- package/src/ui/fx-container.js +5 -0
- package/src/ui/fx-control-menu.js +23 -14
- package/src/ui/fx-control.js +55 -15
- package/src/ui/fx-items.js +10 -4
- package/src/ui/fx-repeat-attributes.js +111 -35
- package/src/ui/fx-repeat.js +332 -85
- package/src/ui/fx-repeat.updated.js +821 -0
- package/src/ui/fx-repeatitem.js +23 -20
- package/src/ui/fx-switch.js +5 -3
- package/src/ui/fx-upload.js +36 -40
- package/src/ui/repeat-base.js +532 -0
- package/src/withDraggability.js +8 -4
- package/src/xpath-evaluation.js +26 -8
- package/src/xpath-path.js +79 -0
- package/src/xpath-util.js +357 -289
package/src/ForeElementMixin.js
CHANGED
|
@@ -1,152 +1,150 @@
|
|
|
1
1
|
import { XPathUtil } from './xpath-util.js';
|
|
2
2
|
import { FxModel } from './fx-model.js';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
evaluateXPath,
|
|
5
|
+
evaluateXPathToFirstNode,
|
|
6
|
+
evaluateXPathToString,
|
|
7
7
|
} from './xpath-evaluation.js';
|
|
8
8
|
import getInScopeContext from './getInScopeContext.js';
|
|
9
9
|
import { Fore } from './fore.js';
|
|
10
10
|
import DependentXPathQueries from './DependentXPathQueries.js';
|
|
11
|
+
import { getPath } from './xpath-path.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Mixin containing all general functions that are shared by all Fore element classes.
|
|
14
15
|
* @extends {HTMLElement}
|
|
15
16
|
*/
|
|
16
17
|
export default class ForeElementMixin extends HTMLElement {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
constructor() {
|
|
56
|
-
super();
|
|
57
|
-
this.context = null;
|
|
58
|
-
this.model = null;
|
|
59
|
-
this.modelItem = null;
|
|
60
|
-
this.ref = this.hasAttribute('ref') ? this.getAttribute('ref') : '';
|
|
61
|
-
/**
|
|
62
|
-
* @type {Map<string, import('./fx-var.js').FxVariable>}
|
|
63
|
-
*/
|
|
64
|
-
this.inScopeVariables = new Map();
|
|
65
|
-
|
|
66
|
-
this.dependencies = new DependentXPathQueries();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
connectedCallback() {
|
|
70
|
-
if (this.parentElement) {
|
|
71
|
-
this.dependencies.setParentDependencies(
|
|
72
|
-
this.parentElement?.closest('[ref]')?.dependencies,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
18
|
+
static get properties() {
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* context object for evaluation
|
|
22
|
+
*/
|
|
23
|
+
context: {
|
|
24
|
+
type: Object,
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* the model of this element
|
|
28
|
+
*/
|
|
29
|
+
model: {
|
|
30
|
+
type: Object,
|
|
31
|
+
},
|
|
32
|
+
/**
|
|
33
|
+
* The modelitem object associated to the bound node holding the evaluated state.
|
|
34
|
+
*/
|
|
35
|
+
modelItem: {
|
|
36
|
+
type: Object,
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* the node(s) bound by this element
|
|
40
|
+
*/
|
|
41
|
+
nodeset: {
|
|
42
|
+
type: Object,
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* XPath binding expression pointing to bound node
|
|
46
|
+
*/
|
|
47
|
+
ref: {
|
|
48
|
+
type: String,
|
|
49
|
+
},
|
|
50
|
+
inScopeVariables: {
|
|
51
|
+
type: Map,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
76
55
|
|
|
56
|
+
constructor() {
|
|
57
|
+
super();
|
|
58
|
+
this.context = null;
|
|
59
|
+
this.model = null;
|
|
60
|
+
this.modelItem = null;
|
|
61
|
+
this.ref = this.hasAttribute('ref') ? this.getAttribute('ref') : '';
|
|
77
62
|
/**
|
|
78
|
-
* @
|
|
63
|
+
* @type {Map<string, import('./fx-var.js').FxVariable>}
|
|
79
64
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
65
|
+
this.inScopeVariables = new Map();
|
|
66
|
+
|
|
67
|
+
this.dependencies = new DependentXPathQueries();
|
|
68
|
+
this.ownerForm = null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
connectedCallback() {
|
|
72
|
+
if (this.parentElement) {
|
|
73
|
+
this.dependencies.setParentDependencies(this.parentElement?.closest('[ref]')?.dependencies);
|
|
89
74
|
}
|
|
90
75
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
getOwnerForm() {
|
|
96
|
-
let currentElement = this;
|
|
97
|
-
while (currentElement && currentElement.parentNode) {
|
|
98
|
-
// console.log('current ', currentElement);
|
|
76
|
+
// The fx-model linked to here won't ever change
|
|
77
|
+
this.model = this.getModel();
|
|
78
|
+
this.ownerForm = this.getOwnerForm();
|
|
79
|
+
}
|
|
99
80
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
81
|
+
/**
|
|
82
|
+
* @returns {import('./fx-model.js').FxModel}
|
|
83
|
+
*/
|
|
84
|
+
getModel() {
|
|
85
|
+
// console.log('getModel this ', this);
|
|
86
|
+
if (this.model) {
|
|
87
|
+
return this.model;
|
|
88
|
+
}
|
|
89
|
+
// const ownerForm = this.closest('fx-fore');
|
|
90
|
+
// const ownerForm = this.getOwnerForm(this);
|
|
91
|
+
const ownerForm = this.getOwnerForm();
|
|
92
|
+
return ownerForm.querySelector('fx-model');
|
|
93
|
+
}
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @returns {import('./fx-fore.js').FxFore} The fx-fore element associated with this form node
|
|
98
|
+
*/
|
|
99
|
+
getOwnerForm() {
|
|
100
|
+
if (this.ownerForm) {
|
|
101
|
+
return this.ownerForm;
|
|
102
|
+
}
|
|
103
|
+
let currentElement = this;
|
|
104
|
+
while (currentElement && currentElement.parentNode) {
|
|
105
|
+
// console.log('current ', currentElement);
|
|
106
|
+
if (currentElement.nodeName.toUpperCase() === 'FX-FORE') {
|
|
110
107
|
return currentElement;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (currentElement.parentNode instanceof DocumentFragment) {
|
|
111
|
+
currentElement = currentElement.parentNode.host;
|
|
112
|
+
} else {
|
|
113
|
+
currentElement = currentElement.parentNode;
|
|
114
|
+
}
|
|
111
115
|
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
112
118
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// console.warn('no in scopeContext for ', this);
|
|
143
|
-
// console.warn('using default context ', this);
|
|
144
|
-
// return;
|
|
145
|
-
}
|
|
146
|
-
if (this.ref === '') {
|
|
147
|
-
this.nodeset = inscopeContext;
|
|
148
|
-
} else if (Array.isArray(inscopeContext)) {
|
|
149
|
-
/*
|
|
119
|
+
/**
|
|
120
|
+
* evaluation of fx-bind and UiElements differ in details so that each class needs it's own implementation.
|
|
121
|
+
*/
|
|
122
|
+
evalInContext() {
|
|
123
|
+
this.dependencies.resetDependencies();
|
|
124
|
+
// const inscopeContext = this.getInScopeContext();
|
|
125
|
+
const model = this.getModel();
|
|
126
|
+
if (!model) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
let inscopeContext;
|
|
130
|
+
if (this.hasAttribute('context')) {
|
|
131
|
+
inscopeContext = getInScopeContext(this.getAttributeNode('context') || this, this.context);
|
|
132
|
+
}
|
|
133
|
+
if (this.hasAttribute('ref')) {
|
|
134
|
+
inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
|
|
135
|
+
this.dependencies.addXPath(this.ref);
|
|
136
|
+
}
|
|
137
|
+
if (!inscopeContext && this.getModel().instances.length !== 0) {
|
|
138
|
+
// ### always fall back to default context with there's neither a 'context' or 'ref' present
|
|
139
|
+
inscopeContext = this.getModel().getDefaultInstance().getDefaultContext();
|
|
140
|
+
// console.warn('no in scopeContext for ', this);
|
|
141
|
+
// console.warn('using default context ', this);
|
|
142
|
+
// return;
|
|
143
|
+
}
|
|
144
|
+
if (this.ref === '') {
|
|
145
|
+
this.nodeset = inscopeContext;
|
|
146
|
+
} else if (Array.isArray(inscopeContext)) {
|
|
147
|
+
/*
|
|
150
148
|
inscopeContext.forEach(n => {
|
|
151
149
|
if (XPathUtil.isSelfReference(this.ref)) {
|
|
152
150
|
this.nodeset = inscopeContext;
|
|
@@ -157,177 +155,184 @@ export default class ForeElementMixin extends HTMLElement {
|
|
|
157
155
|
}
|
|
158
156
|
});
|
|
159
157
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
);
|
|
172
|
-
} else {
|
|
173
|
-
[this.nodeset] = evaluateXPath(this.ref, inscopeContext, this);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// console.log('UiElement evaluated to nodeset: ', this.nodeset);
|
|
158
|
+
// this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext[0], this);
|
|
159
|
+
this.nodeset = evaluateXPath(this.ref, inscopeContext[0], this);
|
|
160
|
+
} else {
|
|
161
|
+
// this.nodeset = fx.evaluateXPathToFirstNode(this.ref, inscopeContext, null, {namespaceResolver: this.namespaceResolver});
|
|
162
|
+
if (!inscopeContext) return;
|
|
163
|
+
const { nodeType } = inscopeContext;
|
|
164
|
+
if (nodeType && !XPathUtil.isAbsolutePath(this.ref)) {
|
|
165
|
+
this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext, this);
|
|
166
|
+
} else {
|
|
167
|
+
[this.nodeset] = evaluateXPath(this.ref, inscopeContext, this);
|
|
168
|
+
}
|
|
177
169
|
}
|
|
170
|
+
// console.log('UiElement evaluated to nodeset: ', this.nodeset);
|
|
171
|
+
}
|
|
178
172
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
return expr;
|
|
173
|
+
/**
|
|
174
|
+
* resolves template expressions for a single attribute
|
|
175
|
+
* @param {string} expr an attribute value containing curly brackets containing XPath expressions to evaluate
|
|
176
|
+
* @param {Node} node the attribute node used for scoped resolution
|
|
177
|
+
* @returns {string}
|
|
178
|
+
* @protected
|
|
179
|
+
*/
|
|
180
|
+
evaluateAttributeTemplateExpression(expr, node) {
|
|
181
|
+
const matches = expr.match(/{[^}]*}/g);
|
|
182
|
+
if (matches) {
|
|
183
|
+
matches.forEach(match => {
|
|
184
|
+
// console.log('match ', match);
|
|
185
|
+
const naked = match.substring(1, match.length - 1);
|
|
186
|
+
const inscope = getInScopeContext(node, naked);
|
|
187
|
+
const result = evaluateXPathToString(naked, inscope, this);
|
|
188
|
+
const replaced = expr.replaceAll(match, result);
|
|
189
|
+
// console.log('replacing ', expr, ' with ', replaced);
|
|
190
|
+
expr = replaced;
|
|
191
|
+
});
|
|
200
192
|
}
|
|
193
|
+
return expr;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
isNotBound() {
|
|
197
|
+
return !this.hasAttribute('ref');
|
|
198
|
+
}
|
|
201
199
|
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
isBound() {
|
|
201
|
+
return this.hasAttribute('ref');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
getBindingExpr() {
|
|
205
|
+
if (this.hasAttribute('ref')) {
|
|
206
|
+
return this.getAttribute('ref');
|
|
207
|
+
}
|
|
208
|
+
// try to get closest parent bind
|
|
209
|
+
const parent = XPathUtil.getClosest('[ref]', this.parentNode);
|
|
210
|
+
if (!parent) {
|
|
211
|
+
return 'instance()'; // the default instance
|
|
204
212
|
}
|
|
213
|
+
return parent.getAttribute('ref');
|
|
214
|
+
}
|
|
205
215
|
|
|
206
|
-
|
|
207
|
-
|
|
216
|
+
/**
|
|
217
|
+
* @returns {import('./fx-instance.js').FxInstance}
|
|
218
|
+
*/
|
|
219
|
+
getInstance() {
|
|
220
|
+
if (this.ref.startsWith('instance(')) {
|
|
221
|
+
const instId = XPathUtil.getInstanceId(this.ref);
|
|
222
|
+
return this.getModel().getInstance(instId);
|
|
208
223
|
}
|
|
224
|
+
return this.getModel().getInstance('default');
|
|
225
|
+
}
|
|
209
226
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
227
|
+
_getParentBindingElement(start) {
|
|
228
|
+
if (start.parentNode.host) {
|
|
229
|
+
const { host } = start.parentNode;
|
|
230
|
+
if (host.hasAttribute('ref')) {
|
|
231
|
+
return host;
|
|
232
|
+
}
|
|
233
|
+
} else if (start.parentNode) {
|
|
234
|
+
if (start.parentNode.hasAttribute('ref')) {
|
|
235
|
+
return this.parentNode;
|
|
236
|
+
}
|
|
237
|
+
this._getParentBindingElement(this.parentNode);
|
|
220
238
|
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
221
241
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
242
|
+
/**
|
|
243
|
+
* @returns {import('./modelitem.js').ModelItem}
|
|
244
|
+
*/
|
|
245
|
+
getModelItem() {
|
|
246
|
+
if (!this.getModel()) return;
|
|
247
|
+
|
|
248
|
+
// First try to find by node reference
|
|
249
|
+
const mi = this.getModel().getModelItem(this.nodeset);
|
|
250
|
+
if (mi) {
|
|
251
|
+
this.modelItem = mi;
|
|
231
252
|
}
|
|
232
253
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
return null;
|
|
254
|
+
const repeated = XPathUtil.getClosest('fx-repeatitem', this);
|
|
255
|
+
let existed;
|
|
256
|
+
if (repeated) {
|
|
257
|
+
const { index } = repeated;
|
|
258
|
+
if (Array.isArray(this.nodeset)) {
|
|
259
|
+
existed = this.getModel().getModelItem(this.nodeset[index - 1]);
|
|
260
|
+
} else {
|
|
261
|
+
existed = this.getModel().getModelItem(this.nodeset);
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
existed = this.nodeset ? this.getModel().getModelItem(this.nodeset) : null;
|
|
246
265
|
}
|
|
247
266
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (mi) {
|
|
255
|
-
this.modelItem = mi;
|
|
256
|
-
}
|
|
267
|
+
// If we couldn't find by node reference, try to find by path
|
|
268
|
+
if (!existed && this.nodeset) {
|
|
269
|
+
// Get the path for the current nodeset
|
|
270
|
+
const instanceId = XPathUtil.resolveInstance(this, this.ref);
|
|
271
|
+
let targetNode =
|
|
272
|
+
this.nodeset.nodeType === Node.TEXT_NODE ? this.nodeset.parentNode : this.nodeset;
|
|
257
273
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (repeated) {
|
|
261
|
-
const { index } = repeated;
|
|
262
|
-
if (Array.isArray(this.nodeset)) {
|
|
263
|
-
existed = this.getModel().getModelItem(this.nodeset[index - 1]);
|
|
264
|
-
} else {
|
|
265
|
-
existed = this.getModel().getModelItem(this.nodeset);
|
|
266
|
-
}
|
|
267
|
-
} else {
|
|
268
|
-
existed = this.nodeset
|
|
269
|
-
? this.getModel().getModelItem(this.nodeset)
|
|
270
|
-
: null;
|
|
271
|
-
}
|
|
274
|
+
if (targetNode?.nodeType) {
|
|
275
|
+
const path = getPath(targetNode, instanceId);
|
|
272
276
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.getModel(),
|
|
276
|
-
this.ref,
|
|
277
|
-
this.nodeset,
|
|
278
|
-
this,
|
|
279
|
-
);
|
|
280
|
-
this.modelItem = lazyCreatedModelItem;
|
|
281
|
-
return lazyCreatedModelItem;
|
|
282
|
-
}
|
|
283
|
-
this.modelItem = existed;
|
|
284
|
-
|
|
285
|
-
return existed;
|
|
286
|
-
}
|
|
277
|
+
// Try to find a ModelItem with this path
|
|
278
|
+
existed = this.getModel().modelItems.find(item => item.path === path);
|
|
287
279
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
* b: look for textContent and return the value if present
|
|
292
|
-
* c: return null
|
|
293
|
-
* @returns {string}
|
|
294
|
-
*/
|
|
295
|
-
getValue() {
|
|
296
|
-
if (this.hasAttribute('value')) {
|
|
297
|
-
const valAttr = this.getAttribute('value');
|
|
298
|
-
try {
|
|
299
|
-
const inscopeContext = getInScopeContext(this, valAttr);
|
|
300
|
-
return evaluateXPathToString(
|
|
301
|
-
valAttr,
|
|
302
|
-
inscopeContext,
|
|
303
|
-
this.getOwnerForm(),
|
|
304
|
-
);
|
|
305
|
-
} catch (error) {
|
|
306
|
-
console.error(error);
|
|
307
|
-
Fore.dispatch(this, 'error', { message: error });
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (this.textContent) {
|
|
311
|
-
return this.textContent;
|
|
280
|
+
if (existed) {
|
|
281
|
+
// Update the node reference in the existing ModelItem
|
|
282
|
+
existed.node = targetNode;
|
|
312
283
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return getInScopeContext(
|
|
321
|
-
this.getAttributeNode('ref') || this,
|
|
322
|
-
this.ref,
|
|
284
|
+
}
|
|
285
|
+
if (!existed) {
|
|
286
|
+
const lazyCreatedModelItem = FxModel.lazyCreateModelItem(
|
|
287
|
+
this.getModel(),
|
|
288
|
+
this.ref,
|
|
289
|
+
this.nodeset,
|
|
290
|
+
this,
|
|
323
291
|
);
|
|
292
|
+
this.modelItem = lazyCreatedModelItem;
|
|
293
|
+
return lazyCreatedModelItem;
|
|
294
|
+
}
|
|
324
295
|
}
|
|
296
|
+
this.modelItem = existed;
|
|
325
297
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
298
|
+
return existed;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Returns the effective value for the element.
|
|
302
|
+
* a: look for 'value' attribute and if present evaluate it and return the resulting value
|
|
303
|
+
* b: look for textContent and return the value if present
|
|
304
|
+
* c: return null
|
|
305
|
+
* @returns {string}
|
|
306
|
+
*/
|
|
307
|
+
getValue() {
|
|
308
|
+
if (this.hasAttribute('value')) {
|
|
309
|
+
const valAttr = this.getAttribute('value');
|
|
310
|
+
try {
|
|
311
|
+
const inscopeContext = getInScopeContext(this, valAttr);
|
|
312
|
+
return evaluateXPathToString(valAttr, inscopeContext, this.getOwnerForm());
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error(error);
|
|
315
|
+
Fore.dispatch(this, 'error', { message: error });
|
|
316
|
+
}
|
|
332
317
|
}
|
|
318
|
+
if (this.textContent) {
|
|
319
|
+
return this.textContent;
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @returns {Node}
|
|
326
|
+
*/
|
|
327
|
+
getInScopeContext() {
|
|
328
|
+
return getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Set variables in scope here
|
|
333
|
+
* @param {Map} inScopeVariables
|
|
334
|
+
*/
|
|
335
|
+
setInScopeVariables(inScopeVariables) {
|
|
336
|
+
this.inScopeVariables = inScopeVariables;
|
|
337
|
+
}
|
|
333
338
|
}
|
|
@@ -4,6 +4,7 @@ import getInScopeContext from '../getInScopeContext.js';
|
|
|
4
4
|
import { Fore } from '../fore.js';
|
|
5
5
|
import { FxFore } from '../fx-fore.js';
|
|
6
6
|
import { XPathUtil } from '../xpath-util.js';
|
|
7
|
+
import { getDocPath } from '../xpath-path.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @param {number} howLong How long to wait, in ms
|
|
@@ -177,7 +178,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
177
178
|
}
|
|
178
179
|
} else {
|
|
179
180
|
this.targetElement = this.parentNode;
|
|
180
|
-
if(!this.targetElement || this.targetElement.nodeType !== Node.ELEMENT_NODE) return;
|
|
181
|
+
if (!this.targetElement || this.targetElement.nodeType !== Node.ELEMENT_NODE) return;
|
|
181
182
|
this.targetElement.addEventListener(this.event, e => this.execute(e), {
|
|
182
183
|
capture: this.phase === 'capture',
|
|
183
184
|
});
|
|
@@ -194,7 +195,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
194
195
|
await Fore.dispatch(this, 'error', {
|
|
195
196
|
origin: this,
|
|
196
197
|
message: 'Action execution failed',
|
|
197
|
-
expr:
|
|
198
|
+
expr: error,
|
|
198
199
|
level: 'Error',
|
|
199
200
|
});
|
|
200
201
|
// Return false to indicate failure. Any loops must be canceled
|
|
@@ -218,15 +219,9 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
218
219
|
// console.log(this, this.event);
|
|
219
220
|
if (this.event) {
|
|
220
221
|
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
|
-
);
|
|
222
|
+
console.info(`📌 ${this.event} #${this?.parentNode?.id}`);
|
|
225
223
|
} 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
|
-
);
|
|
224
|
+
console.info(`📌 ${this.constructor.name} ${this.event}`);
|
|
230
225
|
}
|
|
231
226
|
} else {
|
|
232
227
|
console.info(
|
|
@@ -406,7 +401,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
406
401
|
this.actionPerformed();
|
|
407
402
|
if (FxFore.outermostHandler === this) {
|
|
408
403
|
console.log(
|
|
409
|
-
`%cfinalizing outermost Action on ${this.getOwnerForm()
|
|
404
|
+
`%cfinalizing outermost Action on ${this.getOwnerForm()?.id}`,
|
|
410
405
|
'background:darkblue; color:white; padding:0.3rem; display:inline-block; white-space: nowrap; border-radius:0.3rem;',
|
|
411
406
|
this,
|
|
412
407
|
);
|
|
@@ -480,7 +475,7 @@ export class AbstractAction extends ForeElementMixin {
|
|
|
480
475
|
// console.log('running update cycle for outermostHandler', this);
|
|
481
476
|
model.recalculate();
|
|
482
477
|
model.revalidate();
|
|
483
|
-
this.getOwnerForm().refresh(
|
|
478
|
+
this.getOwnerForm().refresh(false);
|
|
484
479
|
this.dispatchActionPerformed();
|
|
485
480
|
} else if (this.needsUpdate) {
|
|
486
481
|
// console.log('Update delayed!');
|