@jinntec/fore 1.3.0 → 1.4.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 +4 -4
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +3 -3
- package/dist/fore.js.map +1 -1
- package/package.json +1 -1
- package/resources/fore.css +6 -1
- package/src/ForeElementMixin.js +4 -0
- package/src/actions/abstract-action.js +77 -35
- package/src/actions/fx-action.js +9 -9
- package/src/actions/fx-append.js +1 -1
- package/src/actions/fx-confirm.js +1 -1
- package/src/actions/fx-copy.js +68 -0
- package/src/actions/fx-delete.js +1 -1
- package/src/actions/fx-dispatch.js +1 -1
- package/src/actions/fx-hide.js +1 -1
- package/src/actions/fx-insert.js +1 -1
- package/src/actions/fx-message.js +1 -1
- package/src/actions/fx-refresh.js +2 -2
- package/src/actions/fx-reload.js +1 -1
- package/src/actions/fx-replace.js +1 -1
- package/src/actions/fx-return.js +1 -1
- package/src/actions/fx-send.js +2 -2
- package/src/actions/fx-setfocus.js +1 -1
- package/src/actions/fx-setvalue.js +1 -1
- package/src/actions/fx-show.js +1 -1
- package/src/actions/fx-toggle.js +1 -1
- package/src/actions/fx-update.js +1 -1
- package/src/fore.js +58 -10
- package/src/fx-bind.js +5 -0
- package/src/fx-fore.js +36 -35
- package/src/fx-instance.js +70 -70
- package/src/fx-model.js +12 -17
- package/src/fx-submission.js +420 -416
- package/src/getInScopeContext.js +2 -4
- package/src/modelitem.js +3 -1
- package/src/ui/abstract-control.js +1 -1
- package/src/ui/fx-control.js +2 -2
- package/src/ui/fx-switch.js +9 -1
- package/src/ui/fx-trigger.js +19 -18
- package/src/xpath-evaluation.js +21 -9
- package/src/xpath-util.js +13 -28
package/src/fx-submission.js
CHANGED
|
@@ -1,479 +1,483 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import {Fore} from './fore.js';
|
|
2
|
+
import {Relevance} from './relevance.js';
|
|
3
|
+
import {foreElementMixin} from './ForeElementMixin.js';
|
|
4
|
+
import {evaluateXPathToString, evaluateXPath} from './xpath-evaluation.js';
|
|
5
5
|
import getInScopeContext from './getInScopeContext.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* todo: validate='false'
|
|
9
9
|
*/
|
|
10
10
|
export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.attachShadow({mode: 'open'});
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
connectedCallback() {
|
|
17
|
+
// this.style.display = 'none';
|
|
18
|
+
this.methods = ['get', 'put', 'post', 'delete', 'head', 'urlencoded-post'];
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
this.model = this.parentNode;
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
// ### initialize properties with defaults
|
|
23
|
+
// if (!this.hasAttribute('id')) throw new Error('id is required');
|
|
24
|
+
if (!this.hasAttribute('id')) console.warn('id is required');
|
|
25
|
+
this.id = this.getAttribute('id');
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
/** if present should be a existing instance id */
|
|
28
|
+
this.instance = this.hasAttribute('instance') ? this.getAttribute('instance') : null;
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
/** if present will determine XPath where to insert a response into when mode is 'replace' */
|
|
31
|
+
this.into = this.hasAttribute('into') ? this.getAttribute('into') : null;
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
/** http method */
|
|
34
|
+
this.method = this.hasAttribute('method') ? this.getAttribute('method') : 'get';
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
/** relevance processing - one of 'remove, keep or empty' */
|
|
37
|
+
this.nonrelevant = this.hasAttribute('nonrelevant')
|
|
38
|
+
? this.getAttribute('nonrelevant')
|
|
39
|
+
: 'remove';
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
/** replace might be 'all', 'instance' or 'none' */
|
|
42
|
+
this.replace = this.hasAttribute('replace') ? this.getAttribute('replace') : 'all';
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
this.serialization = this.hasAttribute('serialization')
|
|
45
|
+
? this.getAttribute('serialization')
|
|
46
|
+
: 'xml';
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
// if (!this.hasAttribute('url')) throw new Error(`url is required for submission: ${this.id}`);
|
|
49
|
+
if (!this.hasAttribute('url')) console.warn(`url is required for submission: ${this.id}`);
|
|
50
|
+
this.url = this.getAttribute('url');
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
this.targetref = this.hasAttribute('targetref') ? this.getAttribute('targetref') : null;
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
this.mediatype = this.hasAttribute('mediatype')
|
|
55
|
+
? this.getAttribute('mediatype')
|
|
56
|
+
: 'application/xml';
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
this.validate = this.getAttribute('validate') ? this.getAttribute('validate') : 'true';
|
|
59
|
+
this.shadowRoot.innerHTML = this.renderHTML();
|
|
60
|
+
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
// eslint-disable-next-line class-methods-use-this
|
|
63
|
+
renderHTML() {
|
|
64
|
+
return `
|
|
65
65
|
<slot></slot>
|
|
66
66
|
`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async submit() {
|
|
70
|
-
await Fore.dispatch(this, 'submit', { submission: this });
|
|
71
|
-
this._submit();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async _submit() {
|
|
75
|
-
console.log('submitting....', this.getAttribute('id'));
|
|
76
|
-
this.evalInContext();
|
|
77
|
-
const model = this.getModel();
|
|
78
|
-
|
|
79
|
-
model.recalculate();
|
|
80
|
-
|
|
81
|
-
if (this.validate==='true') {
|
|
82
|
-
const valid = model.revalidate();
|
|
83
|
-
if (!valid) {
|
|
84
|
-
console.log('validation failed. Submission stopped');
|
|
85
|
-
this.getOwnerForm().classList.add('submit-validation-failed');
|
|
86
|
-
// ### allow alerts to pop up
|
|
87
|
-
// this.dispatch('submit-error', {});
|
|
88
|
-
Fore.dispatch(this, 'submit-error', {});
|
|
89
|
-
this.getModel().parentNode.refresh(true);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
67
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* resolves template expressions for a single attribute
|
|
99
|
-
* @param expr the attribute value to evaluate
|
|
100
|
-
* @param node the attribute node used for scoped resolution
|
|
101
|
-
* @returns {*}
|
|
102
|
-
* @private
|
|
103
|
-
*/
|
|
104
|
-
_evaluateAttributeTemplateExpression(expr, node) {
|
|
105
|
-
const matches = expr.match(/{[^}]*}/g);
|
|
106
|
-
if (matches) {
|
|
107
|
-
matches.forEach(match => {
|
|
108
|
-
console.log('match ', match);
|
|
109
|
-
const naked = match.substring(1, match.length - 1);
|
|
110
|
-
const inscope = getInScopeContext(node, naked);
|
|
111
|
-
const result = evaluateXPathToString(naked, inscope, this.getOwnerForm());
|
|
112
|
-
const replaced = expr.replaceAll(match, result);
|
|
113
|
-
console.log('replacing ', expr, ' with ', replaced);
|
|
114
|
-
expr = replaced;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
return expr;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* sends the data after evaluating
|
|
122
|
-
*
|
|
123
|
-
* @private
|
|
124
|
-
*/
|
|
125
|
-
async _serializeAndSend() {
|
|
126
|
-
const resolvedUrl = this._evaluateAttributeTemplateExpression(this.url, this);
|
|
127
|
-
|
|
128
|
-
const instance = this.getInstance();
|
|
129
|
-
console.log('instance type', instance.type);
|
|
130
|
-
|
|
131
|
-
let serialized;
|
|
132
|
-
if (this.serialization === 'none') {
|
|
133
|
-
serialized = undefined;
|
|
134
|
-
} else {
|
|
135
|
-
// const relevant = this.selectRelevant(instance.type);
|
|
136
|
-
const relevant = Relevance.selectRelevant(this, instance.type);
|
|
137
|
-
serialized = this._serialize(instance.type, relevant);
|
|
68
|
+
|
|
69
|
+
async submit() {
|
|
70
|
+
await Fore.dispatch(this, 'submit', {submission: this});
|
|
71
|
+
await this._submit();
|
|
138
72
|
}
|
|
139
73
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
74
|
+
async _submit() {
|
|
75
|
+
console.log('submitting....', this.getAttribute('id'));
|
|
76
|
+
this.evalInContext();
|
|
77
|
+
const model = this.getModel();
|
|
78
|
+
|
|
79
|
+
model.recalculate();
|
|
80
|
+
|
|
81
|
+
if (this.validate === 'true') {
|
|
82
|
+
const valid = model.revalidate();
|
|
83
|
+
if (!valid) {
|
|
84
|
+
console.log('validation failed. Submission stopped');
|
|
85
|
+
this.getOwnerForm().classList.add('submit-validation-failed');
|
|
86
|
+
// ### allow alerts to pop up
|
|
87
|
+
// this.dispatch('submit-error', {});
|
|
88
|
+
Fore.dispatch(this, 'submit-error', {});
|
|
89
|
+
this.getModel().parentNode.refresh(true);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
console.log('model updated....');
|
|
94
|
+
await this._serializeAndSend();
|
|
143
95
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* resolves template expressions for a single attribute
|
|
99
|
+
* @param expr the attribute value to evaluate
|
|
100
|
+
* @param node the attribute node used for scoped resolution
|
|
101
|
+
* @returns {*}
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
104
|
+
_evaluateAttributeTemplateExpression(expr, node) {
|
|
105
|
+
const matches = expr.match(/{[^}]*}/g);
|
|
106
|
+
if (matches) {
|
|
107
|
+
matches.forEach(match => {
|
|
108
|
+
console.log('match ', match);
|
|
109
|
+
const naked = match.substring(1, match.length - 1);
|
|
110
|
+
const inscope = getInScopeContext(node, naked);
|
|
111
|
+
const result = evaluateXPathToString(naked, inscope, this.getOwnerForm());
|
|
112
|
+
const replaced = expr.replaceAll(match, result);
|
|
113
|
+
console.log('replacing ', expr, ' with ', replaced);
|
|
114
|
+
expr = replaced;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return expr;
|
|
154
118
|
}
|
|
155
119
|
|
|
156
|
-
|
|
120
|
+
/**
|
|
121
|
+
* sends the data after evaluating
|
|
122
|
+
*
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
125
|
+
async _serializeAndSend() {
|
|
126
|
+
const resolvedUrl = this._evaluateAttributeTemplateExpression(this.url, this);
|
|
127
|
+
|
|
128
|
+
const instance = this.getInstance();
|
|
129
|
+
console.log('instance type', instance.type);
|
|
157
130
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return;
|
|
131
|
+
let serialized;
|
|
132
|
+
if (this.serialization === 'none') {
|
|
133
|
+
serialized = undefined;
|
|
134
|
+
} else {
|
|
135
|
+
// const relevant = this.selectRelevant(instance.type);
|
|
136
|
+
const relevant = Relevance.selectRelevant(this, instance.type);
|
|
137
|
+
serialized = this._serialize(instance.type, relevant);
|
|
166
138
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if(this.method === '
|
|
170
|
-
|
|
139
|
+
|
|
140
|
+
// let serialized = serializer.serializeToString(relevant);
|
|
141
|
+
if (this.method.toLowerCase() === 'get') {
|
|
142
|
+
serialized = undefined;
|
|
143
|
+
}
|
|
144
|
+
// console.log('data being send', serialized);
|
|
145
|
+
// console.log('submitting data',serialized);
|
|
146
|
+
|
|
147
|
+
// if (resolvedUrl === '#echo') {
|
|
148
|
+
if (resolvedUrl.startsWith('#echo')) {
|
|
149
|
+
const data = this._parse(serialized, instance);
|
|
150
|
+
this._handleResponse(data);
|
|
151
|
+
// this.dispatch('submit-done', {});
|
|
152
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
153
|
+
return;
|
|
171
154
|
}
|
|
172
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
173
|
-
}
|
|
174
|
-
if(this.method === 'post'){
|
|
175
|
-
// let data = this._parse(serialized, instance);
|
|
176
|
-
const key = resolvedUrl.substring(resolvedUrl.indexOf(':')+1);
|
|
177
|
-
localStorage.setItem(key,serialized);
|
|
178
|
-
this._handleResponse(instance.instanceData);
|
|
179
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
180
|
-
}
|
|
181
|
-
if(this.method === 'delete'){
|
|
182
|
-
const key = resolvedUrl.substring(resolvedUrl.indexOf(':')+1);
|
|
183
|
-
localStorage.removeItem(key);
|
|
184
|
-
const newInst = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
185
|
-
this._handleResponse(newInst);
|
|
186
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
187
|
-
}
|
|
188
155
|
|
|
189
|
-
|
|
190
|
-
|
|
156
|
+
if (resolvedUrl.startsWith('localStore:')) {
|
|
157
|
+
|
|
158
|
+
if (this.method === 'get' || this.method === 'consume') {
|
|
159
|
+
// let data = this._parse(serialized, instance);
|
|
160
|
+
this.replace = 'instance';
|
|
161
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
162
|
+
const serialized = localStorage.getItem(key);
|
|
163
|
+
if (!serialized) {
|
|
164
|
+
Fore.dispatch(this, 'submit-error', {message: `Error reading key ${key} from localstorage`});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let data = this._parse(serialized, instance);
|
|
168
|
+
this._handleResponse(data);
|
|
169
|
+
if (this.method === 'consume') {
|
|
170
|
+
localStorage.removeItem(key);
|
|
171
|
+
}
|
|
172
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
173
|
+
}
|
|
174
|
+
if (this.method === 'post') {
|
|
175
|
+
// let data = this._parse(serialized, instance);
|
|
176
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
177
|
+
localStorage.setItem(key, serialized);
|
|
178
|
+
this._handleResponse(instance.instanceData);
|
|
179
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
180
|
+
}
|
|
181
|
+
if (this.method === 'delete') {
|
|
182
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':') + 1);
|
|
183
|
+
localStorage.removeItem(key);
|
|
184
|
+
const newInst = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
185
|
+
this._handleResponse(newInst);
|
|
186
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
187
|
+
}
|
|
191
188
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
console.log('headers', headers);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
195
191
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
try{
|
|
202
|
-
const response = await fetch(resolvedUrl, {
|
|
203
|
-
method: this.method,
|
|
204
|
-
mode: 'cors',
|
|
205
|
-
credentials: 'include',
|
|
206
|
-
headers,
|
|
207
|
-
body: serialized,
|
|
208
|
-
});
|
|
192
|
+
// ### setting headers
|
|
193
|
+
const headers = this._getHeaders();
|
|
194
|
+
console.log('headers', headers);
|
|
209
195
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
196
|
+
if (!this.methods.includes(this.method.toLowerCase())) {
|
|
197
|
+
// this.dispatch('error', { message: `Unknown method ${this.method}` });
|
|
198
|
+
Fore.dispatch(this, 'error', {message: `Unknown method ${this.method}`});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const response = await fetch(resolvedUrl, {
|
|
203
|
+
method: this.method,
|
|
204
|
+
mode: 'cors',
|
|
205
|
+
credentials: 'include',
|
|
206
|
+
headers,
|
|
207
|
+
body: serialized,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (!response.ok || response.status > 400) {
|
|
211
|
+
// this.dispatch('submit-error', { message: `Error while submitting ${this.id}` });
|
|
212
|
+
Fore.dispatch(this, 'submit-error', {message: `Error while submitting ${this.id}`});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
216
|
+
const contentType = response.headers.get('content-type').toLowerCase();
|
|
217
|
+
if (
|
|
218
|
+
contentType.startsWith('text/plain') ||
|
|
219
|
+
contentType.startsWith('text/html') ||
|
|
220
|
+
contentType.startsWith('text/markdown')
|
|
221
|
+
) {
|
|
222
|
+
const text = await response.text();
|
|
223
|
+
this._handleResponse(text);
|
|
224
|
+
} else if (contentType.startsWith('application/json')) {
|
|
225
|
+
const json = await response.json();
|
|
226
|
+
this._handleResponse(json);
|
|
227
|
+
} else if (contentType.startsWith('application/xml')) {
|
|
228
|
+
const text = await response.text();
|
|
229
|
+
const xml = new DOMParser().parseFromString(text, 'application/xml');
|
|
230
|
+
this._handleResponse(xml);
|
|
231
|
+
} else {
|
|
232
|
+
const blob = await response.blob();
|
|
233
|
+
this._handleResponse(blob);
|
|
234
|
+
}
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
// this.dispatch('submit-done', {});
|
|
237
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
238
|
+
} catch (error) {
|
|
239
|
+
Fore.dispatch(this, 'submit-error', {error: error.message});
|
|
240
|
+
}
|
|
240
241
|
}
|
|
241
|
-
}
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
_serialize(instanceType, relevantNodes) {
|
|
255
|
-
if (this.serialization === 'application/x-www-form-urlencoded') {
|
|
256
|
-
// this.method = 'post';
|
|
257
|
-
const params = new URLSearchParams();
|
|
258
|
-
// console.log('nodes to serialize', relevantNodes);
|
|
259
|
-
Array.from(relevantNodes.children).forEach(child => {
|
|
260
|
-
params.append(child.nodeName, child.textContent);
|
|
261
|
-
});
|
|
262
|
-
return params;
|
|
263
|
-
}
|
|
264
|
-
if (instanceType === 'xml') {
|
|
265
|
-
const serializer = new XMLSerializer();
|
|
266
|
-
return serializer.serializeToString(relevantNodes);
|
|
243
|
+
_parse(serialized, instance) {
|
|
244
|
+
let data = null;
|
|
245
|
+
if (serialized && instance.type === 'xml') {
|
|
246
|
+
data = new DOMParser().parseFromString(serialized, 'application/xml');
|
|
247
|
+
}
|
|
248
|
+
if (serialized && instance.type === 'json') {
|
|
249
|
+
data = JSON.parse(serialized);
|
|
250
|
+
}
|
|
251
|
+
return data;
|
|
267
252
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
253
|
+
|
|
254
|
+
_serialize(instanceType, relevantNodes) {
|
|
255
|
+
if (this.serialization === 'application/x-www-form-urlencoded') {
|
|
256
|
+
// this.method = 'post';
|
|
257
|
+
const params = new URLSearchParams();
|
|
258
|
+
// console.log('nodes to serialize', relevantNodes);
|
|
259
|
+
Array.from(relevantNodes.children).forEach(child => {
|
|
260
|
+
params.append(child.nodeName, child.textContent);
|
|
261
|
+
});
|
|
262
|
+
return params;
|
|
263
|
+
}
|
|
264
|
+
if (instanceType === 'xml') {
|
|
265
|
+
const serializer = new XMLSerializer();
|
|
266
|
+
return serializer.serializeToString(relevantNodes);
|
|
267
|
+
}
|
|
268
|
+
if (instanceType === 'json') {
|
|
269
|
+
// console.warn('JSON serialization is not yet supported')
|
|
270
|
+
return JSON.stringify(relevantNodes);
|
|
271
|
+
}
|
|
272
|
+
throw new Error('unknown instance type ', instanceType);
|
|
271
273
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
274
|
+
|
|
275
|
+
_getHeaders() {
|
|
276
|
+
const headers = new Headers();
|
|
277
|
+
|
|
278
|
+
// ### set content-type header according to type of instance
|
|
279
|
+
const instance = this.getInstance();
|
|
280
|
+
const contentType = Fore.getContentType(instance, this.serialization);
|
|
281
|
+
headers.append('Content-Type', contentType);
|
|
282
|
+
// ### needed to overwrite browsers' setting of 'Accept' header
|
|
283
|
+
if (headers.has('Accept')) {
|
|
284
|
+
headers.delete('Accept');
|
|
285
|
+
}
|
|
286
|
+
// headers.append('Accept', 'application/xml');
|
|
287
|
+
|
|
288
|
+
// ### add header defined by fx-header elements
|
|
289
|
+
const headerElems = this.querySelectorAll('fx-header');
|
|
290
|
+
Array.from(headerElems).forEach(header => {
|
|
291
|
+
const {name} = header;
|
|
292
|
+
const val = header.getValue();
|
|
293
|
+
headers.append(name, val);
|
|
294
|
+
});
|
|
295
|
+
return headers;
|
|
285
296
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const headerElems = this.querySelectorAll('fx-header');
|
|
290
|
-
Array.from(headerElems).forEach(header => {
|
|
291
|
-
const { name } = header;
|
|
292
|
-
const val = header.getValue();
|
|
293
|
-
headers.append(name, val);
|
|
294
|
-
});
|
|
295
|
-
return headers;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
_getUrlExpr() {
|
|
299
|
-
return this.storedTemplateExpressions.find(stored => stored.node.nodeName === 'url');
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
_getTargetInstance() {
|
|
303
|
-
let targetInstance;
|
|
304
|
-
if (this.instance) {
|
|
305
|
-
targetInstance = this.model.getInstance(this.instance);
|
|
306
|
-
} else {
|
|
307
|
-
targetInstance = this.model.getInstance('default');
|
|
297
|
+
|
|
298
|
+
_getUrlExpr() {
|
|
299
|
+
return this.storedTemplateExpressions.find(stored => stored.node.nodeName === 'url');
|
|
308
300
|
}
|
|
309
|
-
|
|
310
|
-
|
|
301
|
+
|
|
302
|
+
_getTargetInstance() {
|
|
303
|
+
let targetInstance;
|
|
304
|
+
if (this.instance) {
|
|
305
|
+
targetInstance = this.model.getInstance(this.instance);
|
|
306
|
+
} else {
|
|
307
|
+
targetInstance = this.model.getInstance('default');
|
|
308
|
+
}
|
|
309
|
+
if (!targetInstance) {
|
|
310
|
+
throw new Error(`target instance not found: ${targetInstance}`);
|
|
311
|
+
}
|
|
312
|
+
return targetInstance;
|
|
311
313
|
}
|
|
312
|
-
return targetInstance;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* handles replacement of instance data from response data.
|
|
317
|
-
*
|
|
318
|
-
* Please note that data might be
|
|
319
|
-
* @param data
|
|
320
|
-
* @private
|
|
321
|
-
*/
|
|
322
|
-
_handleResponse(data) {
|
|
323
|
-
console.log('_handleResponse ', data);
|
|
324
314
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
315
|
+
/**
|
|
316
|
+
* handles replacement of instance data from response data.
|
|
317
|
+
*
|
|
318
|
+
* Please note that data might be
|
|
319
|
+
* @param data
|
|
320
|
+
* @private
|
|
321
|
+
*/
|
|
322
|
+
_handleResponse(data) {
|
|
323
|
+
console.log('_handleResponse ', data);
|
|
328
324
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
this.
|
|
338
|
-
targetInstance
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
325
|
+
/*
|
|
326
|
+
// ### responses need to be handled depending on their type.
|
|
327
|
+
if(this.type === 'json'){
|
|
328
|
+
|
|
329
|
+
}
|
|
330
|
+
*/
|
|
331
|
+
|
|
332
|
+
if (this.replace === 'instance') {
|
|
333
|
+
const targetInstance = this._getTargetInstance();
|
|
334
|
+
if (targetInstance) {
|
|
335
|
+
if (this.targetref) {
|
|
336
|
+
const [theTarget] = evaluateXPath(
|
|
337
|
+
this.targetref,
|
|
338
|
+
targetInstance.instanceData.firstElementChild,
|
|
339
|
+
this,
|
|
340
|
+
);
|
|
341
|
+
console.log('theTarget', theTarget);
|
|
342
|
+
const clone = data.firstElementChild;
|
|
343
|
+
const parent = theTarget.parentNode;
|
|
344
|
+
parent.replaceChild(clone, theTarget);
|
|
345
|
+
console.log('finally ', parent);
|
|
346
|
+
} else if (this.into) {
|
|
347
|
+
const [theTarget] = evaluateXPath(
|
|
348
|
+
this.into,
|
|
349
|
+
targetInstance.instanceData.firstElementChild,
|
|
350
|
+
this,
|
|
351
|
+
);
|
|
352
|
+
console.log('theTarget', theTarget);
|
|
353
|
+
if (data.nodeType === Node.DOCUMENT_NODE) {
|
|
354
|
+
theTarget.appendChild(data.firstElementChild);
|
|
355
|
+
} else {
|
|
356
|
+
theTarget.innerHTML = data;
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
const instanceData = data;
|
|
360
|
+
targetInstance.instanceData = instanceData;
|
|
361
|
+
console.log('### replaced instance ', this.getModel().instances);
|
|
362
|
+
console.log('### replaced instance ', targetInstance.instanceData);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Skip any refreshes if the model is not yet inited
|
|
366
|
+
if (this.model.inited) {
|
|
367
|
+
this.model.updateModel(); // force update
|
|
368
|
+
this.getOwnerForm().refresh(true);
|
|
369
|
+
}
|
|
370
|
+
} else {
|
|
371
|
+
throw new Error(`target instance not found: ${targetInstance}`);
|
|
372
|
+
}
|
|
363
373
|
}
|
|
364
374
|
|
|
365
|
-
this.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
375
|
+
if (this.replace === 'all') {
|
|
376
|
+
document.getElementsByTagName('html')[0].innerHTML = data;
|
|
377
|
+
}
|
|
378
|
+
if (this.replace === 'target') {
|
|
379
|
+
const target = this.getAttribute('target');
|
|
380
|
+
const targetNode = document.querySelector(target);
|
|
381
|
+
targetNode.innerHTML = data;
|
|
382
|
+
}
|
|
383
|
+
if (this.replace === 'redirect') {
|
|
384
|
+
window.location.href = data;
|
|
385
|
+
}
|
|
370
386
|
}
|
|
371
387
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
388
|
+
/**
|
|
389
|
+
* select relevant nodes
|
|
390
|
+
*
|
|
391
|
+
* @returns {*}
|
|
392
|
+
*/
|
|
393
|
+
/*
|
|
394
|
+
selectRelevant(type) {
|
|
395
|
+
console.log('selectRelevant' ,type)
|
|
396
|
+
switch (type){
|
|
397
|
+
case 'xml':
|
|
398
|
+
return this._relevantXmlNodes();
|
|
399
|
+
default:
|
|
400
|
+
console.warn(`relevance selection not supported for type:${this.type}`);
|
|
401
|
+
return this.nodeset;
|
|
402
|
+
}
|
|
382
403
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
/*
|
|
391
|
-
selectRelevant(type) {
|
|
392
|
-
console.log('selectRelevant' ,type)
|
|
393
|
-
switch (type){
|
|
394
|
-
case 'xml':
|
|
395
|
-
return this._relevantXmlNodes();
|
|
396
|
-
default:
|
|
397
|
-
console.warn(`relevance selection not supported for type:${this.type}`);
|
|
404
|
+
*/
|
|
405
|
+
|
|
406
|
+
// todo: support for 'empty'
|
|
407
|
+
/*
|
|
408
|
+
_relevantXmlNodes() {
|
|
409
|
+
// ### no relevance selection - current nodeset is used 'as-is'
|
|
410
|
+
if (this.nonrelevant === 'keep') {
|
|
398
411
|
return this.nodeset;
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
*/
|
|
402
|
-
|
|
403
|
-
// todo: support for 'empty'
|
|
404
|
-
/*
|
|
405
|
-
_relevantXmlNodes() {
|
|
406
|
-
// ### no relevance selection - current nodeset is used 'as-is'
|
|
407
|
-
if (this.nonrelevant === 'keep') {
|
|
408
|
-
return this.nodeset;
|
|
409
|
-
}
|
|
412
|
+
}
|
|
410
413
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
+
// first check if nodeset of submission is relevant - otherwise bail out
|
|
415
|
+
const mi = this.getModel().getModelItem(this.nodeset);
|
|
416
|
+
if (mi && !mi.relevant) return null;
|
|
414
417
|
|
|
415
|
-
|
|
416
|
-
|
|
418
|
+
const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
419
|
+
const root = doc.firstElementChild;
|
|
417
420
|
|
|
418
|
-
|
|
419
|
-
|
|
421
|
+
if (this.nodeset.children.length === 0 && this._isRelevant(this.nodeset)) {
|
|
422
|
+
return this.nodeset;
|
|
423
|
+
}
|
|
424
|
+
return this._filterRelevant(this.nodeset, root);
|
|
420
425
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
426
|
+
*/
|
|
427
|
+
|
|
428
|
+
/*
|
|
429
|
+
_filterRelevant(node, result) {
|
|
430
|
+
const { childNodes } = node;
|
|
431
|
+
Array.from(childNodes).forEach(n => {
|
|
432
|
+
if (this._isRelevant(n)) {
|
|
433
|
+
const clone = n.cloneNode(false);
|
|
434
|
+
result.appendChild(clone);
|
|
435
|
+
const { attributes } = n;
|
|
436
|
+
if (attributes) {
|
|
437
|
+
Array.from(attributes).forEach(attr => {
|
|
438
|
+
if (this._isRelevant(attr)) {
|
|
439
|
+
clone.setAttribute(attr.nodeName, attr.value);
|
|
440
|
+
} else if (this.nonrelevant === 'empty') {
|
|
441
|
+
clone.setAttribute(attr.nodeName, '');
|
|
442
|
+
} else {
|
|
443
|
+
clone.removeAttribute(attr.nodeName);
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
return this._filterRelevant(n, clone);
|
|
443
448
|
}
|
|
444
|
-
return
|
|
445
|
-
}
|
|
446
|
-
return
|
|
447
|
-
});
|
|
448
|
-
return result;
|
|
449
|
-
}
|
|
450
|
-
*/
|
|
451
|
-
|
|
452
|
-
/*
|
|
453
|
-
_isRelevant(node) {
|
|
454
|
-
const mi = this.getModel().getModelItem(node);
|
|
455
|
-
if (!mi || mi.relevant) {
|
|
456
|
-
return true;
|
|
449
|
+
return null;
|
|
450
|
+
});
|
|
451
|
+
return result;
|
|
457
452
|
}
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
*/
|
|
453
|
+
*/
|
|
461
454
|
|
|
462
|
-
_handleError() {
|
|
463
|
-
// this.dispatch('submit-error', {});
|
|
464
|
-
Fore.dispatch(this, 'submit-error', {});
|
|
465
455
|
/*
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
456
|
+
_isRelevant(node) {
|
|
457
|
+
const mi = this.getModel().getModelItem(node);
|
|
458
|
+
if (!mi || mi.relevant) {
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
*/
|
|
464
|
+
|
|
465
|
+
_handleError() {
|
|
466
|
+
// this.dispatch('submit-error', {});
|
|
467
|
+
Fore.dispatch(this, 'submit-error', {});
|
|
468
|
+
/*
|
|
469
|
+
console.log('ERRRORRRRR');
|
|
470
|
+
this.dispatchEvent(
|
|
471
|
+
new CustomEvent('submit-error', {
|
|
472
|
+
composed: true,
|
|
473
|
+
bubbles: true,
|
|
474
|
+
detail: {},
|
|
475
|
+
}),
|
|
476
|
+
);
|
|
477
|
+
*/
|
|
478
|
+
}
|
|
476
479
|
}
|
|
480
|
+
|
|
477
481
|
if (!customElements.get('fx-submission')) {
|
|
478
|
-
|
|
482
|
+
customElements.define('fx-submission', FxSubmission);
|
|
479
483
|
}
|