@jinntec/fore 1.3.0 → 1.5.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.
Files changed (44) hide show
  1. package/dist/fore-dev.js +8 -8
  2. package/dist/fore-dev.js.map +1 -1
  3. package/dist/fore.js +7 -7
  4. package/dist/fore.js.map +1 -1
  5. package/index.js +1 -0
  6. package/package.json +1 -1
  7. package/resources/fore.css +6 -1
  8. package/src/ForeElementMixin.js +4 -0
  9. package/src/actions/abstract-action.js +117 -48
  10. package/src/actions/fx-action.js +9 -9
  11. package/src/actions/fx-append.js +1 -1
  12. package/src/actions/fx-confirm.js +1 -1
  13. package/src/actions/fx-copy.js +68 -0
  14. package/src/actions/fx-delete.js +1 -1
  15. package/src/actions/fx-dispatch.js +1 -1
  16. package/src/actions/fx-hide.js +1 -1
  17. package/src/actions/fx-insert.js +1 -1
  18. package/src/actions/fx-message.js +1 -1
  19. package/src/actions/fx-refresh.js +2 -2
  20. package/src/actions/fx-reload.js +1 -1
  21. package/src/actions/fx-replace.js +1 -1
  22. package/src/actions/fx-return.js +1 -1
  23. package/src/actions/fx-send.js +2 -2
  24. package/src/actions/fx-setfocus.js +1 -1
  25. package/src/actions/fx-setvalue.js +1 -1
  26. package/src/actions/fx-show.js +1 -1
  27. package/src/actions/fx-toggle.js +1 -1
  28. package/src/actions/fx-update.js +1 -1
  29. package/src/fore.js +59 -10
  30. package/src/fx-bind.js +5 -0
  31. package/src/fx-fore.js +92 -35
  32. package/src/fx-instance.js +70 -70
  33. package/src/fx-model.js +12 -17
  34. package/src/fx-submission.js +420 -416
  35. package/src/getInScopeContext.js +19 -5
  36. package/src/modelitem.js +3 -1
  37. package/src/ui/abstract-control.js +1 -1
  38. package/src/ui/fx-control.js +2 -2
  39. package/src/ui/fx-repeat-attributes.js +442 -0
  40. package/src/ui/fx-repeat.js +8 -0
  41. package/src/ui/fx-switch.js +9 -1
  42. package/src/ui/fx-trigger.js +19 -18
  43. package/src/xpath-evaluation.js +21 -9
  44. package/src/xpath-util.js +13 -28
@@ -1,479 +1,483 @@
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';
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
- constructor() {
12
- super();
13
- this.attachShadow({ mode: 'open' });
14
- }
11
+ constructor() {
12
+ super();
13
+ this.attachShadow({mode: 'open'});
14
+ }
15
15
 
16
- connectedCallback() {
17
- // this.style.display = 'none';
18
- this.methods = ['get', 'put', 'post', 'delete', 'head', 'urlencoded-post'];
16
+ connectedCallback() {
17
+ // this.style.display = 'none';
18
+ this.methods = ['get', 'put', 'post', 'delete', 'head', 'urlencoded-post'];
19
19
 
20
- this.model = this.parentNode;
20
+ this.model = this.parentNode;
21
21
 
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');
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
- /** if present should be a existing instance id */
28
- this.instance = this.hasAttribute('instance') ? this.getAttribute('instance') : null;
27
+ /** if present should be a existing instance id */
28
+ this.instance = this.hasAttribute('instance') ? this.getAttribute('instance') : null;
29
29
 
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;
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
- /** http method */
34
- this.method = this.hasAttribute('method') ? this.getAttribute('method') : 'get';
33
+ /** http method */
34
+ this.method = this.hasAttribute('method') ? this.getAttribute('method') : 'get';
35
35
 
36
- /** relevance processing - one of 'remove, keep or empty' */
37
- this.nonrelevant = this.hasAttribute('nonrelevant')
38
- ? this.getAttribute('nonrelevant')
39
- : 'remove';
36
+ /** relevance processing - one of 'remove, keep or empty' */
37
+ this.nonrelevant = this.hasAttribute('nonrelevant')
38
+ ? this.getAttribute('nonrelevant')
39
+ : 'remove';
40
40
 
41
- /** replace might be 'all', 'instance' or 'none' */
42
- this.replace = this.hasAttribute('replace') ? this.getAttribute('replace') : 'all';
41
+ /** replace might be 'all', 'instance' or 'none' */
42
+ this.replace = this.hasAttribute('replace') ? this.getAttribute('replace') : 'all';
43
43
 
44
- this.serialization = this.hasAttribute('serialization')
45
- ? this.getAttribute('serialization')
46
- : 'xml';
44
+ this.serialization = this.hasAttribute('serialization')
45
+ ? this.getAttribute('serialization')
46
+ : 'xml';
47
47
 
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');
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
- this.targetref = this.hasAttribute('targetref') ? this.getAttribute('targetref') : null;
52
+ this.targetref = this.hasAttribute('targetref') ? this.getAttribute('targetref') : null;
53
53
 
54
- this.mediatype = this.hasAttribute('mediatype')
55
- ? this.getAttribute('mediatype')
56
- : 'application/xml';
54
+ this.mediatype = this.hasAttribute('mediatype')
55
+ ? this.getAttribute('mediatype')
56
+ : 'application/xml';
57
57
 
58
- this.validate = this.getAttribute('validate') ? this.getAttribute('validate') : 'true';
59
- this.shadowRoot.innerHTML = this.renderHTML();
60
- }
58
+ this.validate = this.getAttribute('validate') ? this.getAttribute('validate') : 'true';
59
+ this.shadowRoot.innerHTML = this.renderHTML();
60
+ }
61
61
 
62
- // eslint-disable-next-line class-methods-use-this
63
- renderHTML() {
64
- return `
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
- console.log('model updated....');
94
- await this._serializeAndSend();
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
- // let serialized = serializer.serializeToString(relevant);
141
- if (this.method.toLowerCase() === 'get') {
142
- serialized = undefined;
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
- // console.log('data being send', serialized);
145
- // console.log('submitting data',serialized);
146
-
147
- // if (resolvedUrl === '#echo') {
148
- if (resolvedUrl.startsWith('#echo')) {
149
- let data = this._parse(serialized, instance);
150
- this._handleResponse(data);
151
- // this.dispatch('submit-done', {});
152
- Fore.dispatch(this, 'submit-done', {});
153
- return;
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
- if(resolvedUrl.startsWith('localStore:')){
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
- 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;
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
- let data = this._parse(serialized, instance);
168
- this._handleResponse(data);
169
- if(this.method === 'consume'){
170
- localStorage.removeItem(key);
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
- return;
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
- // ### setting headers
193
- const headers = this._getHeaders();
194
- console.log('headers', headers);
189
+ return;
190
+ }
195
191
 
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
- });
192
+ // ### setting headers
193
+ const headers = this._getHeaders();
194
+ console.log('headers', headers);
209
195
 
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
- }
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
- 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
- }
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
- // this.dispatch('submit-done', {});
237
- Fore.dispatch(this, 'submit-done', {});
238
- } catch (error){
239
- Fore.dispatch(this, 'submit-error', {error:error.message});
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
- _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;
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
- if (instanceType === 'json') {
269
- // console.warn('JSON serialization is not yet supported')
270
- return JSON.stringify(relevantNodes);
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
- throw new Error('unknown instance type ', instanceType);
273
- }
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');
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
- // 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;
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
- if (!targetInstance) {
310
- throw new Error(`target instance not found: ${targetInstance}`);
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
- // ### responses need to be handled depending on their type.
327
- if(this.type === 'json'){
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
- 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);
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.model.updateModel(); // force update
366
- this.getOwnerForm().refresh(true);
367
- } else {
368
- throw new Error(`target instance not found: ${targetInstance}`);
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
- if (this.replace === 'all') {
373
- document.getElementsByTagName('html')[0].innerHTML = data;
374
- }
375
- if (this.replace === 'target') {
376
- const target = this.getAttribute('target');
377
- const targetNode = document.querySelector(target);
378
- targetNode.innerHTML = data;
379
- }
380
- if (this.replace === 'redirect') {
381
- window.location.href = data;
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
- * select relevant nodes
387
- *
388
- * @returns {*}
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
- // first check if nodeset of submission is relevant - otherwise bail out
412
- const mi = this.getModel().getModelItem(this.nodeset);
413
- if (mi && !mi.relevant) return null;
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
- const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
416
- const root = doc.firstElementChild;
418
+ const doc = new DOMParser().parseFromString('<data></data>', 'application/xml');
419
+ const root = doc.firstElementChild;
417
420
 
418
- if (this.nodeset.children.length === 0 && this._isRelevant(this.nodeset)) {
419
- return this.nodeset;
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
- return this._filterRelevant(this.nodeset, root);
422
- }
423
- */
424
-
425
- /*
426
- _filterRelevant(node, result) {
427
- const { childNodes } = node;
428
- Array.from(childNodes).forEach(n => {
429
- if (this._isRelevant(n)) {
430
- const clone = n.cloneNode(false);
431
- result.appendChild(clone);
432
- const { attributes } = n;
433
- if (attributes) {
434
- Array.from(attributes).forEach(attr => {
435
- if (this._isRelevant(attr)) {
436
- clone.setAttribute(attr.nodeName, attr.value);
437
- } else if (this.nonrelevant === 'empty') {
438
- clone.setAttribute(attr.nodeName, '');
439
- } else {
440
- clone.removeAttribute(attr.nodeName);
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 this._filterRelevant(n, clone);
445
- }
446
- return null;
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
- return false;
459
- }
460
- */
453
+ */
461
454
 
462
- _handleError() {
463
- // this.dispatch('submit-error', {});
464
- Fore.dispatch(this, 'submit-error', {});
465
455
  /*
466
- console.log('ERRRORRRRR');
467
- this.dispatchEvent(
468
- new CustomEvent('submit-error', {
469
- composed: true,
470
- bubbles: true,
471
- detail: {},
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
- customElements.define('fx-submission', FxSubmission);
482
+ customElements.define('fx-submission', FxSubmission);
479
483
  }