@jinntec/fore 1.0.0-4 → 1.1.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 +26 -38
- package/dist/fore-dev.js +43 -0
- package/dist/fore-dev.js.map +1 -0
- package/dist/fore.js +37 -0
- package/dist/fore.js.map +1 -0
- package/index.js +4 -0
- package/package.json +42 -42
- package/resources/fore.css +186 -0
- package/resources/toastify.css +87 -0
- package/resources/{fore-styles.css → vars.css} +0 -292
- package/src/DependencyNotifyingDomFacade.js +10 -16
- package/src/ForeElementMixin.js +26 -19
- package/src/actions/abstract-action.js +30 -9
- package/src/actions/fx-action.js +6 -4
- package/src/actions/fx-append.js +8 -17
- package/src/actions/fx-confirm.js +5 -3
- package/src/actions/fx-delete.js +6 -3
- package/src/actions/fx-dispatch.js +9 -8
- package/src/actions/fx-hide.js +10 -6
- package/src/actions/fx-insert.js +49 -39
- package/src/actions/fx-message.js +3 -1
- package/src/actions/fx-refresh.js +15 -1
- package/src/actions/fx-replace.js +73 -0
- package/src/actions/fx-return.js +42 -0
- package/src/actions/fx-send.js +3 -1
- package/src/actions/fx-setfocus.js +37 -0
- package/src/actions/fx-setvalue.js +58 -51
- package/src/actions/fx-show.js +12 -4
- package/src/actions/fx-toggle.js +15 -10
- package/src/actions/fx-update.js +3 -1
- package/src/dep_graph.js +4 -2
- package/src/drawdown.js +67 -82
- package/src/fore.js +158 -12
- package/src/functions/fx-function.js +17 -3
- package/src/fx-bind.js +42 -202
- package/src/fx-fore.js +599 -567
- package/src/fx-header.js +3 -1
- package/src/fx-instance.js +9 -1
- package/src/fx-model.js +59 -23
- package/src/fx-submission.js +106 -48
- package/src/fx-var.js +7 -4
- package/src/getInScopeContext.js +37 -11
- package/src/modelitem.js +4 -4
- package/src/relevance.js +64 -0
- package/src/ui/abstract-control.js +64 -37
- package/src/ui/fx-alert.js +7 -1
- package/src/ui/fx-case.js +4 -3
- package/src/ui/fx-container.js +7 -1
- package/src/ui/fx-control.js +309 -34
- package/src/ui/fx-dialog.js +54 -40
- package/src/ui/fx-group.js +3 -1
- package/src/ui/fx-hint.js +4 -1
- package/src/ui/fx-inspector.js +120 -17
- package/src/ui/fx-items.js +8 -8
- package/src/ui/fx-output.js +16 -5
- package/src/ui/fx-repeat.js +33 -41
- package/src/ui/fx-repeatitem.js +10 -4
- package/src/ui/fx-switch.js +5 -3
- package/src/ui/fx-trigger.js +3 -1
- package/src/xpath-evaluation.js +621 -576
- package/src/xpath-util.js +15 -8
- package/dist/fore-all.js +0 -140
- package/dist/fore-debug.js +0 -140
- package/src/.DS_Store +0 -0
- package/src/actions/.DS_Store +0 -0
- package/src/ui/.DS_Store +0 -0
package/src/relevance.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export class Relevance {
|
|
2
|
+
static selectRelevant(element, type) {
|
|
3
|
+
console.log('selectRelevant', type);
|
|
4
|
+
switch (type) {
|
|
5
|
+
case 'xml':
|
|
6
|
+
return Relevance._relevantXmlNodes(element);
|
|
7
|
+
default:
|
|
8
|
+
console.warn(`relevance selection not supported for type:${element.type}`);
|
|
9
|
+
return element.nodeset;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static _relevantXmlNodes(element) {
|
|
14
|
+
// ### no relevance selection - current nodeset is used 'as-is'
|
|
15
|
+
const nonrelevant = element.getAttribute('nonrelevant');
|
|
16
|
+
if (nonrelevant === 'keep') {
|
|
17
|
+
return element.nodeset;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// first check if nodeset of submission is relevant - otherwise bail out
|
|
21
|
+
const mi = element.getModel().getModelItem(element.nodeset);
|
|
22
|
+
if (mi && !mi.relevant) return null;
|
|
23
|
+
|
|
24
|
+
const root = element.nodeset.cloneNode(false);
|
|
25
|
+
|
|
26
|
+
if (element.nodeset.children.length === 0 && Relevance._isRelevant(element, element.nodeset)) {
|
|
27
|
+
return element.nodeset;
|
|
28
|
+
}
|
|
29
|
+
return Relevance._filterRelevant(element, element.nodeset, root);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static _filterRelevant(element, node, result) {
|
|
33
|
+
const { childNodes } = node;
|
|
34
|
+
Array.from(childNodes).forEach(n => {
|
|
35
|
+
if (Relevance._isRelevant(element, n)) {
|
|
36
|
+
const clone = n.cloneNode(false);
|
|
37
|
+
result.appendChild(clone);
|
|
38
|
+
const { attributes } = n;
|
|
39
|
+
if (attributes) {
|
|
40
|
+
Array.from(attributes).forEach(attr => {
|
|
41
|
+
if (Relevance._isRelevant(element, attr)) {
|
|
42
|
+
clone.setAttribute(attr.nodeName, attr.value);
|
|
43
|
+
} else if (element.nonrelevant === 'empty') {
|
|
44
|
+
clone.setAttribute(attr.nodeName, '');
|
|
45
|
+
} else {
|
|
46
|
+
clone.removeAttribute(attr.nodeName);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return Relevance._filterRelevant(element, n, clone);
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
});
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static _isRelevant(element, node) {
|
|
58
|
+
const mi = element.getModel().getModelItem(node);
|
|
59
|
+
if (!mi || mi.relevant) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import '../fx-model.js';
|
|
2
2
|
import { foreElementMixin } from '../ForeElementMixin.js';
|
|
3
3
|
import { ModelItem } from '../modelitem.js';
|
|
4
|
+
import { Fore } from '../fore.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* `AbstractControl` -
|
|
@@ -26,7 +27,7 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
26
27
|
/**
|
|
27
28
|
* (re)apply all modelItem state properties to this control. model -> UI
|
|
28
29
|
*/
|
|
29
|
-
async refresh(
|
|
30
|
+
async refresh() {
|
|
30
31
|
// console.log('### AbstractControl.refresh on : ', this);
|
|
31
32
|
|
|
32
33
|
const currentVal = this.value;
|
|
@@ -36,6 +37,7 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
36
37
|
|
|
37
38
|
// await this.updateComplete;
|
|
38
39
|
// await this.getWidget();
|
|
40
|
+
this.oldVal = this.nodeset ? this.nodeset : null;
|
|
39
41
|
this.evalInContext();
|
|
40
42
|
|
|
41
43
|
if (this.isBound()) {
|
|
@@ -51,12 +53,36 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
51
53
|
if (this.modelItem instanceof ModelItem) {
|
|
52
54
|
// console.log('### XfAbstractControl.refresh modelItem : ', this.modelItem);
|
|
53
55
|
|
|
54
|
-
this.
|
|
56
|
+
if (this.hasAttribute('as') && this.getAttribute('as') === 'node') {
|
|
57
|
+
console.log('as', this.nodeset);
|
|
58
|
+
this.modelItem.value = this.nodeset;
|
|
59
|
+
this.value = this.modelItem.node;
|
|
60
|
+
} else {
|
|
61
|
+
this.value = this.modelItem.value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// console.log('value of widget',this.value);
|
|
65
|
+
|
|
66
|
+
/*
|
|
67
|
+
* todo: find out on which foreign modelitems we might be dependant on when no binds are used.
|
|
68
|
+
*
|
|
69
|
+
* e.g. filter expr on 'ref' 'instance('countries')//country[@continent = instance('default')/continent]'
|
|
70
|
+
*
|
|
71
|
+
* the country node is dependant on instance('default')/continent here (foreign node).
|
|
72
|
+
*
|
|
73
|
+
* possible approach:
|
|
74
|
+
* - pipe ref expression through DependencyNotifyingDomFacade to get referred nodes.
|
|
75
|
+
* - lookup modelItems of referred nodes
|
|
76
|
+
* - add ourselves to boundControls of foreign modelItem -> this control will then get refreshed when the foreign modelItem is changed.
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
// const touched = FxBind.getReferencesForRef(this.ref,Array.from(this.nodeset));
|
|
80
|
+
// console.log('touched',touched);
|
|
55
81
|
|
|
56
82
|
/*
|
|
57
83
|
this is another case that highlights the fact that an init() function might make sense in general.
|
|
58
84
|
*/
|
|
59
|
-
if(!this.modelItem.boundControls.includes(this)){
|
|
85
|
+
if (!this.modelItem.boundControls.includes(this)) {
|
|
60
86
|
this.modelItem.boundControls.push(this);
|
|
61
87
|
}
|
|
62
88
|
|
|
@@ -68,15 +94,10 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
68
94
|
// if(!this.closest('fx-fore').ready) return; // state change event do not fire during init phase (initial refresh)
|
|
69
95
|
if (!this.getOwnerForm().ready) return; // state change event do not fire during init phase (initial refresh)
|
|
70
96
|
if (currentVal !== this.value) {
|
|
71
|
-
|
|
72
|
-
// console.log('value-changed path ', this.modelItem.path);
|
|
73
|
-
this.dispatch('value-changed', { path: this.modelItem.path });
|
|
97
|
+
Fore.dispatch(this, 'value-changed', { path: this.modelItem.path });
|
|
74
98
|
}
|
|
75
|
-
// this.requestUpdate();
|
|
76
99
|
}
|
|
77
100
|
}
|
|
78
|
-
// Fore.refreshChildren(this,force);
|
|
79
|
-
// await this.updateComplete;
|
|
80
101
|
}
|
|
81
102
|
|
|
82
103
|
/**
|
|
@@ -89,13 +110,14 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
89
110
|
}
|
|
90
111
|
|
|
91
112
|
handleModelItemProperties() {
|
|
92
|
-
// console.log('
|
|
113
|
+
// console.log('handleModelItemProperties',this.modelItem);
|
|
93
114
|
this.handleRequired();
|
|
94
115
|
this.handleReadonly();
|
|
95
116
|
if (this.getOwnerForm().ready) {
|
|
96
117
|
this.handleValid();
|
|
97
118
|
}
|
|
98
119
|
this.handleRelevant();
|
|
120
|
+
// todo: handleType()
|
|
99
121
|
}
|
|
100
122
|
|
|
101
123
|
_getForm() {
|
|
@@ -104,43 +126,46 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
104
126
|
|
|
105
127
|
_dispatchEvent(event) {
|
|
106
128
|
if (this.getOwnerForm().ready) {
|
|
107
|
-
|
|
129
|
+
Fore.dispatch(this, event, {});
|
|
108
130
|
}
|
|
109
131
|
}
|
|
110
132
|
|
|
111
133
|
// eslint-disable-next-line class-methods-use-this
|
|
112
134
|
handleRequired() {
|
|
113
135
|
// console.log('mip required', this.modelItem.required);
|
|
114
|
-
// const control = this.querySelector('#control');
|
|
115
136
|
this.widget = this.getWidget();
|
|
116
|
-
if (this.
|
|
137
|
+
// if (this.required !== this.modelItem.required) {
|
|
138
|
+
// if (this.isRequired() !== this.modelItem.required) {
|
|
117
139
|
if (this.modelItem.required) {
|
|
118
|
-
this.
|
|
119
|
-
|
|
140
|
+
if (this.getOwnerForm().ready){
|
|
141
|
+
if(this.widget.value === ''){
|
|
142
|
+
this.classList.add('isRequiredFalse');
|
|
143
|
+
}else{
|
|
144
|
+
this.classList.remove('isRequiredFalse');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
this.widget.setAttribute('required', '');
|
|
148
|
+
this.setAttribute('required', '');
|
|
120
149
|
this._dispatchEvent('required');
|
|
121
150
|
} else {
|
|
122
151
|
this.widget.removeAttribute('required');
|
|
123
|
-
this.required
|
|
124
|
-
// this.removeAttribute('required');
|
|
125
|
-
this.classList.toggle('required');
|
|
152
|
+
this.removeAttribute('required');
|
|
126
153
|
this._dispatchEvent('optional');
|
|
127
154
|
}
|
|
128
|
-
}
|
|
155
|
+
// }
|
|
129
156
|
}
|
|
130
157
|
|
|
131
158
|
handleReadonly() {
|
|
132
159
|
// console.log('mip readonly', this.modelItem.isReadonly);
|
|
133
160
|
if (this.isReadonly() !== this.modelItem.readonly) {
|
|
134
161
|
if (this.modelItem.readonly) {
|
|
135
|
-
this.widget.setAttribute('readonly', '
|
|
136
|
-
|
|
137
|
-
this.classList.toggle('readonly');
|
|
162
|
+
this.widget.setAttribute('readonly', '');
|
|
163
|
+
this.setAttribute('readonly', '');
|
|
138
164
|
this._dispatchEvent('readonly');
|
|
139
165
|
}
|
|
140
166
|
if (!this.modelItem.readonly) {
|
|
141
167
|
this.widget.removeAttribute('readonly');
|
|
142
|
-
|
|
143
|
-
this.classList.toggle('readonly');
|
|
168
|
+
this.removeAttribute('readonly');
|
|
144
169
|
this._dispatchEvent('readwrite');
|
|
145
170
|
}
|
|
146
171
|
}
|
|
@@ -153,12 +178,12 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
153
178
|
|
|
154
179
|
if (this.isValid() !== this.modelItem.constraint) {
|
|
155
180
|
if (this.modelItem.constraint) {
|
|
156
|
-
this.classList.remove('invalid');
|
|
157
181
|
if (alert) alert.style.display = 'none';
|
|
158
182
|
this._dispatchEvent('valid');
|
|
183
|
+
this.removeAttribute('invalid');
|
|
159
184
|
} else {
|
|
185
|
+
this.setAttribute('invalid', '');
|
|
160
186
|
// ### constraint is invalid - handle alerts
|
|
161
|
-
this.classList.add('invalid');
|
|
162
187
|
if (alert) {
|
|
163
188
|
alert.style.display = 'block';
|
|
164
189
|
}
|
|
@@ -185,6 +210,12 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
185
210
|
|
|
186
211
|
handleRelevant() {
|
|
187
212
|
// console.log('mip valid', this.modelItem.enabled);
|
|
213
|
+
const item = this.modelItem.node;
|
|
214
|
+
if (Array.isArray(item) && item.length === 0) {
|
|
215
|
+
this._dispatchEvent('nonrelevant');
|
|
216
|
+
this.style.display = 'none';
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
188
219
|
if (this.isEnabled() !== this.modelItem.relevant) {
|
|
189
220
|
if (this.modelItem.relevant) {
|
|
190
221
|
this._dispatchEvent('relevant');
|
|
@@ -199,14 +230,12 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
199
230
|
}
|
|
200
231
|
|
|
201
232
|
isRequired() {
|
|
202
|
-
|
|
203
|
-
return true;
|
|
204
|
-
}
|
|
205
|
-
return false;
|
|
233
|
+
return this.hasAttribute('required');
|
|
206
234
|
}
|
|
207
235
|
|
|
208
236
|
isValid() {
|
|
209
|
-
|
|
237
|
+
// return this.valid;
|
|
238
|
+
if (this.hasAttribute('invalid')) {
|
|
210
239
|
return false;
|
|
211
240
|
}
|
|
212
241
|
return true;
|
|
@@ -214,10 +243,7 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
214
243
|
|
|
215
244
|
isReadonly() {
|
|
216
245
|
// const widget = this.querySelector('#widget');
|
|
217
|
-
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
return false;
|
|
246
|
+
return this.hasAttribute('readonly');
|
|
221
247
|
}
|
|
222
248
|
|
|
223
249
|
isEnabled() {
|
|
@@ -257,5 +283,6 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
257
283
|
})();
|
|
258
284
|
}
|
|
259
285
|
}
|
|
260
|
-
|
|
261
|
-
window.customElements.define('fx-abstract-control', AbstractControl);
|
|
286
|
+
if (!customElements.get('fx-abstract-control')) {
|
|
287
|
+
window.customElements.define('fx-abstract-control', AbstractControl);
|
|
288
|
+
}
|
package/src/ui/fx-alert.js
CHANGED
|
@@ -29,9 +29,15 @@ export class FxAlert extends AbstractControl {
|
|
|
29
29
|
`;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
getWidget() {
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
async updateWidgetValue() {
|
|
33
37
|
console.log('alert update', this);
|
|
34
38
|
this.innerHTML = this.value;
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
|
-
customElements.
|
|
41
|
+
if (!customElements.get('fx-alert')) {
|
|
42
|
+
customElements.define('fx-alert', FxAlert);
|
|
43
|
+
}
|
package/src/ui/fx-case.js
CHANGED
|
@@ -26,7 +26,7 @@ class FxCase extends HTMLElement {
|
|
|
26
26
|
|
|
27
27
|
const style = `
|
|
28
28
|
:host {
|
|
29
|
-
|
|
29
|
+
visibility: none;
|
|
30
30
|
}
|
|
31
31
|
`;
|
|
32
32
|
const html = `
|
|
@@ -40,8 +40,9 @@ class FxCase extends HTMLElement {
|
|
|
40
40
|
${html}
|
|
41
41
|
`;
|
|
42
42
|
|
|
43
|
-
this.style.display = 'none';
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
if (!customElements.get('fx-case')) {
|
|
47
|
+
window.customElements.define('fx-case', FxCase);
|
|
48
|
+
}
|
package/src/ui/fx-container.js
CHANGED
|
@@ -44,6 +44,10 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
44
44
|
if (this.isBound()) {
|
|
45
45
|
this.evalInContext();
|
|
46
46
|
this.modelItem = this.getModelItem();
|
|
47
|
+
if (!this.modelItem.boundControls.includes(this)) {
|
|
48
|
+
this.modelItem.boundControls.push(this);
|
|
49
|
+
}
|
|
50
|
+
|
|
47
51
|
// this.value = this.modelItem.value;
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -107,4 +111,6 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
|
|
|
107
111
|
}
|
|
108
112
|
}
|
|
109
113
|
|
|
110
|
-
|
|
114
|
+
if (!customElements.get('fx-container')) {
|
|
115
|
+
window.customElements.define('fx-container', FxContainer);
|
|
116
|
+
}
|